From 2b653a3e248cc91e02b12b4e91bc0022919f6089 Mon Sep 17 00:00:00 2001 From: Jennie Jia Date: Fri, 3 Aug 2018 18:33:40 +0000 Subject: [PATCH] Merge the POMBA code to ONAP AAI data router Issue-ID: LOG-588 Change-Id: I5d121121e1f6b8167cc0f6b3326b488aedf01430 Signed-off-by: Jennie Jia --- pom.xml | 60 +-- .../onap/aai/datarouter/entity/POAAuditEvent.java | 88 +++++ .../entity/POAServiceInstanceEntity.java | 173 +++++++++ .../datarouter/exception/POAAuditException.java | 87 +++++ .../aai/datarouter/logging/DataRouterMsgs.java | 417 +++++++++++---------- .../logging/ServiceIntegrityValidationsMsgs.java | 63 ++++ .../policy/ServiceIntegrityValidationPolicy.java | 213 +++++++++++ .../onap/aai/datarouter/service/AuditService.java | 205 ++++++++++ .../aai/datarouter/util/DataRouterProperties.java | 120 +++--- .../org/onap/aai/datarouter/util/LoggingUtil.java | 96 +++++ .../resources/auditservice_validation_schema.json | 20 + .../resources/auditservice_violation_schema.json | 16 + .../ServiceIntegrityValidationsMsgs.properties | 37 ++ .../entity/POAServiceInstanceEntityTest.java | 281 ++++++++++++++ .../exception/POAAuditExceptionTest.java | 53 +++ .../ServiceIntegrityValidationPolicyStubbed.java | 67 ++++ .../ServiceIntegrityValidationPolicyTest.java | 112 ++++++ .../aai/datarouter/service/AuditServiceTest.java | 65 ++++ src/test/resources/poa_audit_result.json | 336 +++++++++++++++++ .../resources/poa_auditservice_validation.json | 27 ++ src/test/resources/poa_auditservice_violation.json | 14 + src/test/resources/poa_event.json | 18 + 22 files changed, 2282 insertions(+), 286 deletions(-) create mode 100644 src/main/java/org/onap/aai/datarouter/entity/POAAuditEvent.java create mode 100644 src/main/java/org/onap/aai/datarouter/entity/POAServiceInstanceEntity.java create mode 100644 src/main/java/org/onap/aai/datarouter/exception/POAAuditException.java create mode 100644 src/main/java/org/onap/aai/datarouter/logging/ServiceIntegrityValidationsMsgs.java create mode 100644 src/main/java/org/onap/aai/datarouter/policy/ServiceIntegrityValidationPolicy.java create mode 100644 src/main/java/org/onap/aai/datarouter/service/AuditService.java create mode 100644 src/main/java/org/onap/aai/datarouter/util/LoggingUtil.java create mode 100644 src/main/resources/auditservice_validation_schema.json create mode 100644 src/main/resources/auditservice_violation_schema.json create mode 100644 src/main/resources/logging/ServiceIntegrityValidationsMsgs.properties create mode 100644 src/test/java/org/onap/aai/datarouter/entity/POAServiceInstanceEntityTest.java create mode 100644 src/test/java/org/onap/aai/datarouter/exception/POAAuditExceptionTest.java create mode 100644 src/test/java/org/onap/aai/datarouter/policy/ServiceIntegrityValidationPolicyStubbed.java create mode 100644 src/test/java/org/onap/aai/datarouter/policy/ServiceIntegrityValidationPolicyTest.java create mode 100644 src/test/java/org/onap/aai/datarouter/service/AuditServiceTest.java create mode 100644 src/test/resources/poa_audit_result.json create mode 100644 src/test/resources/poa_auditservice_validation.json create mode 100644 src/test/resources/poa_auditservice_violation.json create mode 100644 src/test/resources/poa_event.json diff --git a/pom.xml b/pom.xml index 7b0a651..28de9b2 100644 --- a/pom.xml +++ b/pom.xml @@ -38,10 +38,10 @@ limitations under the License. 2.20.0 ${basedir}/target /appl/${project.artifactId} - /appl/${project.artifactId}/${project.version} @@ -49,8 +49,8 @@ limitations under the License. aaiadmin com.att.csid.lab - 0 9502 @@ -121,7 +121,7 @@ limitations under the License. javax.ws.rs javax.ws.rs-api - 2.0.1 + 2.1 org.powermock @@ -175,7 +175,7 @@ limitations under the License. - + @@ -226,7 +226,7 @@ limitations under the License. 1.1.0 - + com.google.guava guava ${version.com.google.guava} @@ -360,27 +360,27 @@ limitations under the License. - + org.sonatype.plugins nexus-staging-maven-plugin diff --git a/src/main/java/org/onap/aai/datarouter/entity/POAAuditEvent.java b/src/main/java/org/onap/aai/datarouter/entity/POAAuditEvent.java new file mode 100644 index 0000000..19c4da1 --- /dev/null +++ b/src/main/java/org/onap/aai/datarouter/entity/POAAuditEvent.java @@ -0,0 +1,88 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * 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.datarouter.entity; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.util.ArrayList; +import java.util.List; +import javax.ws.rs.core.Response.Status; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.datarouter.exception.POAAuditException; +import org.onap.aai.datarouter.logging.DataRouterMsgs; + +/** + * Wrapper class for POMBA rest call message body + * + */ +public class POAAuditEvent +{ + private static final String ATTR_SERVICE_INST_LIST = "serviceInstanceList"; + + private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + private List serviceInstanceList = new ArrayList(); + + private static Logger logger = LoggerFactory.getInstance().getLogger(POAAuditEvent.class.getName()); + + public String toJson() { + return gson.toJson(this); + } + + public static POAAuditEvent fromJson(String payload) throws POAAuditException { + if (payload == null || payload.isEmpty()) { + throw new POAAuditException("Invalid Json Payload", Status.BAD_REQUEST); + } + + try { + return gson.fromJson(payload, POAAuditEvent.class); + } catch (Exception ex) { + logger.debug("Invalid Json Payload: " + payload); + throw new POAAuditException("Invalid Json Payload", Status.BAD_REQUEST, DataRouterMsgs.BAD_REST_REQUEST, ex.getMessage()); + } + } + + public List getServiceInstanceList() { + return serviceInstanceList; + } + + public void setServiceInstanceList(List instances) { + this.serviceInstanceList = instances; + } + + + /** + * Validates this service instance list + * @throws POAAuditException if the list is absent or empty + */ + public void validate() throws POAAuditException { + + if((serviceInstanceList == null) || serviceInstanceList.isEmpty()) { + String error = "Missing attribute list: " + ATTR_SERVICE_INST_LIST; + throw new POAAuditException(error, Status.BAD_REQUEST, DataRouterMsgs.BAD_REST_REQUEST, error); + } + } + + @Override + public String toString() { + return "AuditEvent [serviceInstances=" + serviceInstanceList + "]"; + } +} diff --git a/src/main/java/org/onap/aai/datarouter/entity/POAServiceInstanceEntity.java b/src/main/java/org/onap/aai/datarouter/entity/POAServiceInstanceEntity.java new file mode 100644 index 0000000..419db87 --- /dev/null +++ b/src/main/java/org/onap/aai/datarouter/entity/POAServiceInstanceEntity.java @@ -0,0 +1,173 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * 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.datarouter.entity; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import javax.ws.rs.core.Response.Status; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.datarouter.exception.POAAuditException; +import org.onap.aai.datarouter.logging.DataRouterMsgs; +import org.onap.aai.datarouter.service.AuditService; + +/** + * This class includes the POMBA rest call message body which triggers the audit process + * + */ +public class POAServiceInstanceEntity +{ + private static final String ATTR_SERVICE_INST_ID = "serviceInstanceId"; + private static final String ATTR_SERVICE_TYPE = "serviceType"; + private static final String ATTR_MODEL_VERSION_ID = "modelVersionId"; + private static final String ATTR_MODEL_INVARIANT_ID = "modelInvariantId"; + private static final String ATTR_CUSTOMER_ID = "customerId"; + + private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + + private String xFromAppId; + private String xTransactionId; + private String serviceInstanceId; + private String serviceType; + private String modelVersionId; + private String modelInvariantId; + private String customerId; + + private static Logger logger = LoggerFactory.getInstance().getLogger(POAServiceInstanceEntity.class.getName()); + + + public String getxFromAppId() { + return xFromAppId; + } + + public void setxFromAppId(String xFromAppId) { + this.xFromAppId = xFromAppId; + } + + public String getxTransactionId() { + return xTransactionId; + } + + public void setxTransactionId(String xTransactionId) { + this.xTransactionId = xTransactionId; + } + + public String getServiceInstanceId() { + return serviceInstanceId; + } + + public void setServiceInstanceId(String serviceInstanceId) { + this.serviceInstanceId = serviceInstanceId; + } + + public String getServiceType() { + return serviceType; + } + + public void setServiceType(String serviceType) { + this.serviceType = serviceType; + } + + public String getModelVersionId() { + return modelVersionId; + } + + public void setModelVersionId(String modelVersionId) { + this.modelVersionId = modelVersionId; + } + + public String getModelInvariantId() { + return modelInvariantId; + } + + public void setModelInvariantId(String modelInvariantId) { + this.modelInvariantId = modelInvariantId; + } + + public String getCustomerId() { + return customerId; + } + + public void setCustomerId(String customerId) { + this.customerId = customerId; + } + + + public String toJson() { + return gson.toJson(this); + } + + + public static POAServiceInstanceEntity fromJson(String payload) throws POAAuditException { + + if (payload == null || payload.isEmpty()) { + throw new POAAuditException("Invalid Json Payload", Status.BAD_REQUEST); + } + + try { + return gson.fromJson(payload, POAServiceInstanceEntity.class); + } catch (Exception ex) { + logger.debug("Invalid Json Payload: " + payload); + throw new POAAuditException("Invalid Json Payload", Status.BAD_REQUEST, DataRouterMsgs.BAD_REST_REQUEST, ex.getMessage()); + } + } + + + /** + * Validates this service instance; only the attributes that are expected in request body are verified. + * @throws POAAuditException if the service instance is invalid + */ + public void validate() throws POAAuditException { + + if(serviceInstanceId == null || serviceInstanceId.isEmpty()) { + String error = "Missing attribute: " + ATTR_SERVICE_INST_ID; + throw new POAAuditException(error, Status.BAD_REQUEST, DataRouterMsgs.BAD_REST_REQUEST, error); + } + + if(serviceType == null || serviceType.isEmpty()) { + String error = "Missing attribute: " + ATTR_SERVICE_TYPE; + throw new POAAuditException(error, Status.BAD_REQUEST, DataRouterMsgs.BAD_REST_REQUEST, error); + } + + if(modelVersionId == null || modelVersionId.isEmpty()) { + String error = "Missing attribute: " + ATTR_MODEL_VERSION_ID; + throw new POAAuditException(error, Status.BAD_REQUEST, DataRouterMsgs.BAD_REST_REQUEST, error); + } + + if(modelInvariantId == null || modelInvariantId.isEmpty()) { + String error = "Missing attribute: " + ATTR_MODEL_INVARIANT_ID; + throw new POAAuditException(error, Status.BAD_REQUEST, DataRouterMsgs.BAD_REST_REQUEST, error); + } + + if(customerId == null || customerId.isEmpty()) { + String error = "Missing attribute: " + ATTR_CUSTOMER_ID; + throw new POAAuditException(error, Status.BAD_REQUEST, DataRouterMsgs.BAD_REST_REQUEST, error); + } + } + + + @Override + public String toString() { + return "ServiceInstance [xFromAppId=" + xFromAppId + ", xTransactionId=" + xTransactionId + + ", serviceInstanceId=" + serviceInstanceId + ", serviceType=" + serviceType + ", modelVersionId=" + + modelVersionId + ", modelInvariantId=" + modelInvariantId + ", customerId=" + customerId + "]"; + } +} diff --git a/src/main/java/org/onap/aai/datarouter/exception/POAAuditException.java b/src/main/java/org/onap/aai/datarouter/exception/POAAuditException.java new file mode 100644 index 0000000..6d99640 --- /dev/null +++ b/src/main/java/org/onap/aai/datarouter/exception/POAAuditException.java @@ -0,0 +1,87 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * 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.datarouter.exception; + +import javax.ws.rs.core.Response.Status; +import org.onap.aai.datarouter.logging.DataRouterMsgs; + +/** + * This class is to handle the POMBA specific exception + * + */ +public class POAAuditException extends Exception { + + private static final long serialVersionUID = 8162385108397238865L; + + private Status httpStatus; + private DataRouterMsgs logCode; + private String[] logArguments; + + public POAAuditException(String messageForResponse, Status httpStatus) { + super(messageForResponse); + this.setHttpStatus(httpStatus); + } + + public POAAuditException(String message, Status httpStatus, Throwable cause) { + super(message, cause); + this.setHttpStatus(httpStatus); + } + + public POAAuditException(Throwable cause) { + super(cause); + } + + public POAAuditException(String message, Throwable cause) { + super(message, cause); + } + + public POAAuditException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public POAAuditException(String message, Status httpStatus, DataRouterMsgs logCode, String... logArgs) { + super(message); + this.setHttpStatus(httpStatus); + this.logCode = logCode; + logArguments = new String[logArgs.length]; + int i = 0; + for(String arg : logArgs) { + logArguments[i++] = arg; + } + } + + public Status getHttpStatus() { + return httpStatus; + } + + public void setHttpStatus(Status httpStatus) { + this.httpStatus = httpStatus; + } + + public DataRouterMsgs getLogCode() { + return logCode; + } + + public String[] getLogArguments() { + return logArguments; + } +} diff --git a/src/main/java/org/onap/aai/datarouter/logging/DataRouterMsgs.java b/src/main/java/org/onap/aai/datarouter/logging/DataRouterMsgs.java index 2443993..5a2f3fa 100644 --- a/src/main/java/org/onap/aai/datarouter/logging/DataRouterMsgs.java +++ b/src/main/java/org/onap/aai/datarouter/logging/DataRouterMsgs.java @@ -1,198 +1,219 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 Amdocs - * ================================================================================ - * 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.datarouter.logging; - -import com.att.eelf.i18n.EELFResourceManager; - -import org.onap.aai.cl.eelf.LogMessageEnum; - -public enum DataRouterMsgs implements LogMessageEnum { - - /** Data Layer Service started. */ - SERVICE_STARTED, - - /** - * Data Layer Service failed to start. - * Arguments: {0} = Exception message. - */ - STARTUP_FAILURE, - - /** - * File has been changed. - * Arguments: {0} = File name. - */ - FILE_CHANGED, - - /** - * File has been reloaded. - * Arguments: {0} = File name. - */ - FILE_RELOADED, - - /** - * Reports the configuration watcher interval. - * Arguments: {0} = Interval - */ - REPORT_CONFIG_WATCHER_INT, - - /** - * Loading properties file. - * Arguments: {0} = File name. - */ - LOADING_PROPERTIES, - - /** - * Properties file has been loaded. - * Arguments: {0} = File name. - */ - PROPERTIES_LOADED, - - /** - * UEB no events received. - * Arguments: {0} = Topic name - */ - UEB_NO_EVENTS_RECEIVED, - - /** - * Routing policies are being configured. - */ - CONFIGURING_ROUTING_POLICIES, - - /** - * A properties file could not be successfully loaded. - * Arguments: {0} = File name. - */ - LOAD_PROPERTIES_FAILURE, - - /** - * Failed to register for an event topic with UEB. - * Arguments: {0} = Topic {1} = Error reason - */ - UEB_CONNECT_ERR, - - /** - * An error occurred while trying to route a query. - * Arguments: {0} = Query {1} = Error reason - */ - QUERY_ROUTING_ERR, - - /** - * Error in file monitor block. - */ - FILE_MON_BLOCK_ERR, - - /** - * Failure to create a property map. - */ - CREATE_PROPERTY_MAP_ERR, - - /** - * An error occurred reading from a file stream. - */ - FILE_STREAM_ERR, - - /** - * An error occurred while trying to configure a routing policy. - * Arguments: {0} = policy name {1} = source of the routing policy {2} = action of the routing - * policy - */ - ROUTING_POLICY_CONFIGURATION_ERROR, - - /** - * Received request {0} {1} from {2}. Sending response: {3} - * Arguments: {0} = operation {1} = target URL {2} = source {3} = response code - */ - PROCESS_REST_REQUEST, - - /** - * Index {0} may not exist in the search data store. Attempting to create it now. - */ - CREATE_MISSING_INDEX, - - /** - * Processed event {0}. Result: {1} - * Arguments: {0} = event topic {1} = result - */ - PROCESS_EVENT, - - /** - * Arguments: {0} = Error - */ - - BAD_REST_REQUEST, - - /** - * Arguments: {0} = Search index URL {1} = Reason - */ - FAIL_TO_CREATE_SEARCH_INDEX, - - /** - * Arguments: {0} = Successfully created index at endpoint - */ - SEARCH_INDEX_CREATE_SUCCESS, - - INVALID_OXM_FILE, - - INVALID_OXM_DIR, - LOAD_OXM_ERROR, - - /** - * Arguments: {0} = origin payload - */ - INVALID_ORIGIN_PAYLOAD, - - /** - * Arguments: {0} = Origin URL {1} = Target outbound URL - */ - ROUTING_FROM_TO, - - /** - * Arguments: {0} = Target outbound URL, {1} = Response - */ - ROUTING_RESPONSE, - - /** - * Failed to create or update document in index {0}. Cause: {1} - * - * Arguments: - * {0} = Index name - * {1} = Failure cause - */ - FAIL_TO_CREATE_UPDATE_DOC, - - /** - * Arguments: {0} = Operation, {1} = Time in ms - */ - OP_TIME, - - /** Arguments: {0} = Schema file location */ - READING_JSON_SCHEMA_ERROR, - - /** Arguments: {0} = Error message */ - JSON_CONVERSION_ERROR; - - /** - * Static initializer to ensure the resource bundles for this class are loaded... - */ - static { - EELFResourceManager.loadMessageBundle("logging/DataRouterMsgs"); - } -} +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * 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.datarouter.logging; + +import com.att.eelf.i18n.EELFResourceManager; +import org.onap.aai.cl.eelf.LogMessageEnum; + +public enum DataRouterMsgs implements LogMessageEnum { + + /** Data Layer Service started. */ + SERVICE_STARTED, + + /** + * Data Layer Service failed to start. + * Arguments: {0} = Exception message. + */ + STARTUP_FAILURE, + + /** + * File has been changed. + * Arguments: {0} = File name. + */ + FILE_CHANGED, + + /** + * File has been reloaded. + * Arguments: {0} = File name. + */ + FILE_RELOADED, + + /** + * Reports the configuration watcher interval. + * Arguments: {0} = Interval + */ + REPORT_CONFIG_WATCHER_INT, + + /** + * Loading properties file. + * Arguments: {0} = File name. + */ + LOADING_PROPERTIES, + + /** + * Properties file has been loaded. + * Arguments: {0} = File name. + */ + PROPERTIES_LOADED, + + /** + * UEB no events received. + * Arguments: {0} = Topic name + */ + UEB_NO_EVENTS_RECEIVED, + + /** + * Routing policies are being configured. + */ + CONFIGURING_ROUTING_POLICIES, + + /** + * A properties file could not be successfully loaded. + * Arguments: {0} = File name. + */ + LOAD_PROPERTIES_FAILURE, + + /** + * Failed to register for an event topic with UEB. + * Arguments: {0} = Topic {1} = Error reason + */ + UEB_CONNECT_ERR, + + /** + * An error occurred while trying to route a query. + * Arguments: {0} = Query {1} = Error reason + */ + QUERY_ROUTING_ERR, + + /** + * Error in file monitor block. + */ + FILE_MON_BLOCK_ERR, + + /** + * Failure to create a property map. + */ + CREATE_PROPERTY_MAP_ERR, + + /** + * An error occurred reading from a file stream. + */ + FILE_STREAM_ERR, + + /** + * An error occurred while trying to configure a routing policy. + * Arguments: {0} = policy name {1} = source of the routing policy {2} = action of the routing + * policy + */ + ROUTING_POLICY_CONFIGURATION_ERROR, + + /** + * Received request {0} {1} from {2}. Sending response: {3} + * Arguments: {0} = operation {1} = target URL {2} = source {3} = response code + */ + PROCESS_REST_REQUEST, + + /** + * Index {0} may not exist in the search data store. Attempting to create it now. + */ + CREATE_MISSING_INDEX, + + /** + * Processed event {0}. Result: {1} + * Arguments: {0} = event topic {1} = result + */ + PROCESS_EVENT, + + /** + * Arguments: {0} = Error + */ + + BAD_REST_REQUEST, + + /** + * Arguments: {0} = Search index URL {1} = Reason + */ + FAIL_TO_CREATE_SEARCH_INDEX, + + /** + * Arguments: {0} = Successfully created index at endpoint + */ + SEARCH_INDEX_CREATE_SUCCESS, + + INVALID_OXM_FILE, + + INVALID_OXM_DIR, + LOAD_OXM_ERROR, + + /** + * Arguments: {0} = origin payload + */ + INVALID_ORIGIN_PAYLOAD, + + /** + * Arguments: {0} = Origin URL {1} = Target outbound URL + */ + ROUTING_FROM_TO, + + /** + * Arguments: {0} = Target outbound URL, {1} = Response + */ + ROUTING_RESPONSE, + + /** + * Failed to create or update document in index {0}. Cause: {1} + * + * Arguments: + * {0} = Index name + * {1} = Failure cause + */ + FAIL_TO_CREATE_UPDATE_DOC, + + /** + * Arguments: {0} = Operation, {1} = Time in ms + */ + OP_TIME, + + /** Arguments: {0} = Schema file location */ + READING_JSON_SCHEMA_ERROR, + + /** Arguments: {0} = Error message */ + JSON_CONVERSION_ERROR, + + /** + * Operation: {0}; URI: {1}; Exception: {2} + */ + EXCEPTION_DURING_METHOD_CALL, + + /** + * Failed to publish {0} event(s) to DMaaP; cause: {1} + * Arguments: {0} = number of events; {1} = cause + */ + FAIL_TO_SEND_TO_DMAAP, + + /** + * Failed to authenticate: {0} + * Arguments: {0} = reason + */ + FAIL_TO_AUTHENTICATE, + + /** + * Invalid value for configuration '{0}'; using default value {1} + * Arguments: {0} config attribute; {1} default value + */ + WARN_USING_DEFAULT; + /** + * Static initializer to ensure the resource bundles for this class are loaded... + */ + static { + EELFResourceManager.loadMessageBundle("logging/DataRouterMsgs"); + } +} diff --git a/src/main/java/org/onap/aai/datarouter/logging/ServiceIntegrityValidationsMsgs.java b/src/main/java/org/onap/aai/datarouter/logging/ServiceIntegrityValidationsMsgs.java new file mode 100644 index 0000000..8d06da4 --- /dev/null +++ b/src/main/java/org/onap/aai/datarouter/logging/ServiceIntegrityValidationsMsgs.java @@ -0,0 +1,63 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * 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.datarouter.logging; + +import com.att.eelf.i18n.EELFResourceManager; +import org.onap.aai.cl.eelf.LogMessageEnum; + +/** + * ENUM class to handle ElasticSearch validation log message + * + */ +public enum ServiceIntegrityValidationsMsgs implements LogMessageEnum { + + /** + * Arguments: N/A + */ + SI_POLICY_REGISTRATION, + /** + * Arguments: + * {0} = Result + * {1} = Additional information + */ + SI_POLICY_DECISION, + + /** + * {0} = Operation + * {1} = Time for operation to complete + */ + OPERATION_RESULT_ERRORS, + + /** + * Arguments: + * {0} = Payload + * {1} = Error + */ + DOCUMENT_STORE_PAYLOAD_FAILURE; + + + /** + * Static initializer to ensure the resource bundles for this class are loaded... + */ + static { + EELFResourceManager.loadMessageBundle("logging/ServiceIntegrityValidationsMsgs"); + } +} diff --git a/src/main/java/org/onap/aai/datarouter/policy/ServiceIntegrityValidationPolicy.java b/src/main/java/org/onap/aai/datarouter/policy/ServiceIntegrityValidationPolicy.java new file mode 100644 index 0000000..31aa898 --- /dev/null +++ b/src/main/java/org/onap/aai/datarouter/policy/ServiceIntegrityValidationPolicy.java @@ -0,0 +1,213 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * 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.datarouter.policy; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.apache.camel.Exchange; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.cl.mdc.MdcContext; +import org.onap.aai.restclient.client.Headers; +import org.onap.aai.datarouter.logging.ServiceIntegrityValidationsMsgs; +import org.onap.aai.datarouter.util.SearchServiceAgent; +import org.slf4j.MDC; + +/** + * This class handles the logic which transformers the POA-AUDIT-RESULT event message to the ElasticSearch validation/violation message + * in order to prepare two Json structures, one for validation index and one for violation index and then submit POST request to + * Search-Data-Service to insert the document into ES. + * + */ +public class ServiceIntegrityValidationPolicy { + + private static final String SERVICE_VALIDATION_SCHEMA_FILE = "auditservice_validation_schema.json"; + private static final String SERVICE_VIOLATION_SCHEMA_FILE = "auditservice_violation_schema.json"; + + private static Logger logger = LoggerFactory.getInstance() + .getLogger(ServiceIntegrityValidationPolicy.class.getSimpleName()); + + private static JsonParser jsonParser = new JsonParser(); + + private String validationIndexName = null; + private String violationIndexName = null; + + private SearchServiceAgent searchAgent = null; + + public ServiceIntegrityValidationPolicy(String searchCertPath, + String searchCertTruststore, + String searchCertPassword, + String searchBaseURL, + String endpoint, + String validationIndexName, + String violationIndexName) { + searchAgent = new SearchServiceAgent(searchCertPath, + searchCertTruststore, + searchCertPassword, + concatSubURI(searchBaseURL, endpoint), + "documents", + logger); + + this.validationIndexName = validationIndexName; + this.violationIndexName = violationIndexName; + } + + public void startup(){ + + searchAgent.createSearchIndex(validationIndexName, SERVICE_VALIDATION_SCHEMA_FILE); + searchAgent.createSearchIndex(violationIndexName, SERVICE_VIOLATION_SCHEMA_FILE); + + logger.info(ServiceIntegrityValidationsMsgs.SI_POLICY_REGISTRATION); + } + + public void process(Exchange exchange) throws Exception { + + logger.debug("Invoking ServiceIntegrityViolationPolicy with payload" + exchange.getIn().getBody()); + + String payload = (String)exchange.getIn().getBody(); + + JsonObject serviceValidation = jsonParser.parse(payload).getAsJsonObject(); + JsonElement serviceViolationsElement = serviceValidation.get("violations"); + // Calculate the document id to use for this entity. + JsonElement id = serviceValidation.get("validationId"); + + if(serviceViolationsElement == null || serviceViolationsElement.getAsJsonArray().size() == 0) { + serviceValidation.addProperty("result", "Pass"); + logger.debug("Service integrity validation event processing for event with ID " + id + " as a Pass due to no violations."); + }else { + serviceValidation.addProperty("result", "Fail"); + logger.debug("Service integrity validation event processing for event with ID " + id + " as a Fail due to one or more violations."); + } + + if(serviceViolationsElement != null) { + JsonArray violationsArray = serviceViolationsElement.getAsJsonArray(); + Iterator vit = violationsArray.iterator(); + while(vit.hasNext()) { + JsonObject currentViolation = vit.next().getAsJsonObject(); + JsonObject oldViolationDetails = currentViolation.getAsJsonObject("violationDetails"); + JsonObject newViolationDetails = new JsonObject(); + for (Map.Entry e : oldViolationDetails.entrySet()) { + String oldKey = e.getKey(); + String newKey = oldKey.replace(".","-"); + newViolationDetails.add(newKey,e.getValue()); + } + currentViolation.remove("violationDetails"); + currentViolation.remove("modelName"); + currentViolation.add("violationDetails",newViolationDetails); + logger.debug("new violation:" + currentViolation.toString()); + JsonObject formattedViolation = buildViolation(serviceValidation, currentViolation); + + handleSearchDataServiceOperation(violationIndexName, null, formattedViolation.toString(), "POST"); + + } + } + logger.debug("validation: " + serviceValidation.toString()); + + JsonObject formattedValidation = buildValidation(serviceValidation); + // Persist the entity that we received from the event to the Search Service. + handleSearchDataServiceOperation(validationIndexName, id.getAsString(), formattedValidation.toString(), "PUT"); + + } + + + private JsonObject buildViolation(JsonObject validation, JsonObject violation) { + JsonObject formattedViolation = new JsonObject(); + + formattedViolation.addProperty("validationId", validation.get("validationId").getAsString()); + formattedViolation.addProperty("validationTimestamp", validation.get("validationTimestamp").getAsString()); + formattedViolation.addProperty("modelVersionId", validation.get("entity").getAsJsonObject().get("poa-event").getAsJsonObject().get("modelVersionId").getAsString()); + formattedViolation.addProperty("modelInvariantId", validation.get("entity").getAsJsonObject().get("poa-event").getAsJsonObject().get("modelInvariantId").getAsString()); + formattedViolation.addProperty("serviceInstanceId",validation.get("entity").getAsJsonObject().get("poa-event").getAsJsonObject().get("serviceInstanceId").getAsString()); + + formattedViolation.addProperty("violationId", violation.get("violationId").getAsString()); + formattedViolation.addProperty("violationTimestamp", validation.get("validationTimestamp").getAsString()); + formattedViolation.addProperty("category", violation.get("category").getAsString()); + formattedViolation.addProperty("severity", violation.get("severity").getAsString()); + formattedViolation.addProperty("violationType", violation.get("violationType").getAsString()); + formattedViolation.addProperty("validationRule", violation.get("validationRule").getAsString()); + formattedViolation.addProperty("message", violation.get("errorMessage").getAsString()); + + //formattedViolation.add("violationDetails",violation.get("violationDetails")); + return formattedViolation; + } + + private JsonObject buildValidation(JsonObject validation) { + JsonObject formattedValidation = new JsonObject(); + + formattedValidation.add("violations", validation.get("violations")); + formattedValidation.addProperty("validationId", validation.get("validationId").getAsString()); + formattedValidation.addProperty("validationTimestamp", validation.get("validationTimestamp").getAsString()); + formattedValidation.addProperty("modelVersionId", validation.get("entity").getAsJsonObject().get("poa-event").getAsJsonObject().get("modelVersionId").getAsString()); + formattedValidation.addProperty("modelInvariantId", validation.get("entity").getAsJsonObject().get("poa-event").getAsJsonObject().get("modelInvariantId").getAsString()); + formattedValidation.addProperty("serviceInstanceId",validation.get("entity").getAsJsonObject().get("poa-event").getAsJsonObject().get("serviceInstanceId").getAsString()); + + try { + formattedValidation.addProperty("modelName", validation.get("entity").getAsJsonObject().get("context-list").getAsJsonObject().get("sdc").getAsJsonObject().get("service").getAsJsonObject().get("name").getAsString()); + logger.debug("model name: " + validation.get("entity").getAsJsonObject().get("context-list").getAsJsonObject().get("sdc").getAsJsonObject().get("service").getAsJsonObject().get("name").getAsString()); + }catch (NullPointerException ex){ + ex.printStackTrace(); + formattedValidation.addProperty("modelName",""); + } + + return formattedValidation; + } + + + private static String concatSubURI(String... suburis) { + String finalURI = ""; + + for (String suburi : suburis) { + + if (suburi != null) { + // Remove any leading / since we only want to append / + suburi = suburi.replaceFirst("^/*", ""); + + // Add a trailing / if one isn't already there + finalURI += suburi.endsWith("/") ? suburi : suburi + "/"; + } + } + + return finalURI; + } + + + public void handleSearchDataServiceOperation(String index, String id, String payload, String action) { + + Map> headers = new HashMap<>(); + headers.put(Headers.FROM_APP_ID, Arrays.asList("DataRouter")); + headers.put(Headers.TRANSACTION_ID, Arrays.asList(MDC.get(MdcContext.MDC_REQUEST_ID))); + + if (action.equalsIgnoreCase("PUT")) { + searchAgent.putDocument(index, id, payload, headers); + + }else if (action.equalsIgnoreCase("POST")) { + searchAgent.postDocument(index, payload, headers); + } + + } +} diff --git a/src/main/java/org/onap/aai/datarouter/service/AuditService.java b/src/main/java/org/onap/aai/datarouter/service/AuditService.java new file mode 100644 index 0000000..a0ab83c --- /dev/null +++ b/src/main/java/org/onap/aai/datarouter/service/AuditService.java @@ -0,0 +1,205 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * 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.datarouter.service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.Encoded; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.aai.cl.mdc.MdcContext; +import org.onap.aai.datarouter.entity.POAAuditEvent; +import org.onap.aai.datarouter.entity.POAServiceInstanceEntity; +import org.onap.aai.datarouter.exception.POAAuditException; +import org.onap.aai.datarouter.logging.DataRouterMsgs; +import org.onap.aai.datarouter.util.LoggingUtil; +import org.onap.aai.event.api.EventPublisher; +import org.onap.aai.datarouter.util.DataRouterConstants; +import org.onap.aai.restclient.client.Headers; + + + +public class AuditService { + + private static Logger logger = LoggerFactory.getInstance().getLogger(AuditService.class.getName()); + private static Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(AuditService.class.getName()); + + private static final String MEDIA_TYPE = MediaType.APPLICATION_JSON; + private static final String DATA_ROUTER_APP = "Data-Router"; + private static final String UNKNOWN_APP = "[unknown_app_id]"; + private static final String RESULT_OK = "200 OK"; + + private EventPublisher publisher; + + public AuditService(EventPublisher publisher) throws Exception { + this.publisher = publisher; + } + + + /** + * Handles an incoming post-orchestration audit request. + * Generates and posts audit events to DMaaP. + * + * @param content - JSON structure containing the request payload + * @param uri - Http request uri + * @param headers - Http request headers + * @param uriInfo - Http URI info field + * @param req - Http request structure. + * @return - Standard HTTP response. + * + */ + @POST + @Path("/orchestration-event/") + @Consumes({MediaType.APPLICATION_JSON}) + @Produces({MediaType.APPLICATION_JSON}) + public Response triggerPOA(String content, + @PathParam("uri") @Encoded String uri, @Context HttpHeaders headers, @Context UriInfo uriInfo, + @Context HttpServletRequest req) { + + logger.debug("Incoming request..." + content); + Response response = null; + try { + Map headerAttributes = initializeLogging(req, headers); + + List serviceInstanceEvents = generateServiceInstanceEvents(headerAttributes, content); + processEvent(serviceInstanceEvents); + + response = Response.status(Status.OK).entity(RESULT_OK).type(MEDIA_TYPE).build(); + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + + } catch(POAAuditException e) { + response = Response.status(e.getHttpStatus()).entity(e.getMessage()).build(); + LoggingUtil.logRestRequest(logger, auditLogger, req, response, e); + } finally { + LoggingUtil.closeMdc(); + } + return response; + } + + + /** + * Initialize MDC logging using attributes from the request + * @param httpReq + * @param httpHeaders + * @return Returns a map of required header attributes + * @throws POAAuditException + */ + private Map initializeLogging(HttpServletRequest httpReq, HttpHeaders httpHeaders) throws POAAuditException { + + Map headers = new HashMap(); + String remoteAddr = httpReq.getRemoteAddr(); + + if (httpHeaders.getRequestHeaders() == null) { + String error="Missing Header"; + throw new POAAuditException(error, Status.BAD_REQUEST, DataRouterMsgs.BAD_REST_REQUEST, error); + } + String transactionId = httpHeaders.getRequestHeaders().getFirst(Headers.TRANSACTION_ID); + if((transactionId == null) || transactionId.trim().isEmpty()) { + transactionId = UUID.randomUUID().toString(); + logger.debug("Header " + Headers.TRANSACTION_ID + "not present in request, generating new value: " + transactionId); + } + headers.put(Headers.TRANSACTION_ID, transactionId); + + String fromAppId = httpHeaders.getRequestHeaders().getFirst(Headers.FROM_APP_ID); + if((fromAppId == null) || fromAppId.trim().isEmpty()) { + // initialize the context before throwing the exception + MdcContext.initialize(transactionId, DataRouterConstants.DATA_ROUTER_SERVICE_NAME, "", UNKNOWN_APP, remoteAddr); + String error = "Missing header attribute: " + Headers.FROM_APP_ID; + throw new POAAuditException(error, Status.BAD_REQUEST, DataRouterMsgs.BAD_REST_REQUEST, error); + } + headers.put(Headers.FROM_APP_ID, fromAppId); + + LoggingUtil.initMdc(transactionId, fromAppId, remoteAddr); + + return headers; + } + + + + /** + * Extracts service instances and generates a list of events + * @param eventHeaders + * @param requestBody + * @return Returns a list of service instances + * @throws POAAuditException if the request contains errors + */ + private List generateServiceInstanceEvents(Map eventHeaders, String requestBody) throws POAAuditException { + + POAAuditEvent auditEvent = POAAuditEvent.fromJson(requestBody); + auditEvent.validate(); + + List eventMessages = new ArrayList(); + for (POAServiceInstanceEntity serviceInstance: auditEvent.getServiceInstanceList()) { + serviceInstance.validate(); + serviceInstance.setxFromAppId(DATA_ROUTER_APP); + serviceInstance.setxTransactionId(eventHeaders.get(Headers.TRANSACTION_ID)); + eventMessages.add(serviceInstance.toJson()); + } + return eventMessages; + } + + + /** + * Publish events to DMaaP. + * @param eventMessages + * @throws POAAuditException + * + * Note: The Default Transport Type in the DMaaPEventPublisher is defined as "HTTPAAF". Based on the deployment of DMaap, currently + * by default the "HTTPAUTH" transport type is supported. + */ + private void processEvent(List eventMessages) throws POAAuditException { + + int messagesSent = 0; + try { + messagesSent = publisher.sendSync(eventMessages); + logger.debug("The number of messages successfully sent: "+ messagesSent); + + if (messagesSent > 0) { + logger.debug("Published Message: " + eventMessages); + } else { + String exceptionStr = String.format("Failed to publish %d event(s) to DMaaP", eventMessages.size()); + logger.debug(exceptionStr); + } + + + } catch (Exception e) { + throw new POAAuditException("Failed to publish event to DMaaP: " + e.getMessage(), Status.INTERNAL_SERVER_ERROR, + DataRouterMsgs.EXCEPTION_DURING_METHOD_CALL, e.getMessage()); + } + + } +} + diff --git a/src/main/java/org/onap/aai/datarouter/util/DataRouterProperties.java b/src/main/java/org/onap/aai/datarouter/util/DataRouterProperties.java index 36e4a10..b24f5bd 100644 --- a/src/main/java/org/onap/aai/datarouter/util/DataRouterProperties.java +++ b/src/main/java/org/onap/aai/datarouter/util/DataRouterProperties.java @@ -1,58 +1,62 @@ -/** - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017-2018 Amdocs - * ================================================================================ - * 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.datarouter.util; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DataRouterProperties { - - private static final Logger LOGGER = LoggerFactory.getLogger(DataRouterProperties.class); - - private static Properties properties; - - static { - File file = new File(DataRouterConstants.DR_CONFIG_FILE); - loadProperties(file); - } - - static void loadProperties(File file) { - properties = new Properties(); - try (InputStream props = new FileInputStream(file)) { - properties.load(props); - } catch (FileNotFoundException e) { - LOGGER.error("FileNotFoundException: ", e); - } catch (IOException e) { - LOGGER.error("IOException: ", e); - } - } - - public static String get(String key) { - return properties.getProperty(key); - } - -} +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * 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.datarouter.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DataRouterProperties { + + private static final Logger LOGGER = LoggerFactory.getLogger(DataRouterProperties.class); + + private static Properties properties; + + static { + File file = new File(DataRouterConstants.DR_CONFIG_FILE); + loadProperties(file); + } + + static void loadProperties(File file) { + properties = new Properties(); + try (InputStream props = new FileInputStream(file)) { + properties.load(props); + } catch (FileNotFoundException e) { + LOGGER.error("FileNotFoundException: ", e); + } catch (IOException e) { + LOGGER.error("IOException: ", e); + } + } + + public static String get(String key) { + return properties.getProperty(key); + } + + public static String get(String key, String defaultValue) { + return properties.getProperty(key, defaultValue); + } + +} diff --git a/src/main/java/org/onap/aai/datarouter/util/LoggingUtil.java b/src/main/java/org/onap/aai/datarouter/util/LoggingUtil.java new file mode 100644 index 0000000..2c9a94c --- /dev/null +++ b/src/main/java/org/onap/aai/datarouter/util/LoggingUtil.java @@ -0,0 +1,96 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * 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.datarouter.util; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.Response; +import org.onap.aai.cl.api.LogFields; +import org.onap.aai.cl.api.LogLine; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.mdc.MdcContext; +import org.onap.aai.datarouter.exception.POAAuditException; +import org.onap.aai.datarouter.logging.DataRouterMsgs; +import org.onap.aai.datarouter.util.DataRouterConstants; +import org.slf4j.MDC; + +public class LoggingUtil { + + private static String UNKNOWN = "unknown"; + + /** + * Initializes MDC context. + * Called when request processing begins. + * @param httpReq + * @param headers + */ + public static void initMdc(String transactionId, String fromAppId, String remoteAddr) { + MdcContext.initialize(transactionId, DataRouterConstants.DATA_ROUTER_SERVICE_NAME, "", fromAppId, remoteAddr); + } + + /** + * Clears the MDC context. + * Called when request processing ends. + */ + public static void closeMdc() { + MDC.clear(); + } + + + /** + * Generates error and audit logs + */ + public static void logRestRequest(Logger logger, Logger auditLogger, HttpServletRequest req, Response response) { + logRestRequest(logger, auditLogger, req, response, null); + } + + + /** + * Generates error and audit logs + * @param logger + * @param auditLogger + * @param req + * @param response + * @param exception + */ + public static void logRestRequest(Logger logger, Logger auditLogger, HttpServletRequest req, Response response, POAAuditException exception) { + + String respStatusString = UNKNOWN; + if(Response.Status.fromStatusCode(response.getStatus()) != null) { + respStatusString = Response.Status.fromStatusCode(response.getStatus()).toString(); + } + + LogFields logFields = new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, response.getStatus()) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, respStatusString); + + if((exception != null) && (exception.getLogCode() != null)) { + logger.error(exception.getLogCode(), exception.getLogArguments()); + auditLogger.error(exception.getLogCode(), logFields, exception.getLogArguments()); + } + + String status = Integer.toString(response.getStatus()); + String method = (req != null) ? req.getMethod() : UNKNOWN; + String reqUrl = (req != null) ? req.getRequestURL().toString() : UNKNOWN; + String remoteHost = (req != null) ? req.getRemoteHost() : UNKNOWN; + + logger.info(DataRouterMsgs.PROCESS_REST_REQUEST, method, reqUrl, remoteHost, status); + auditLogger.info(DataRouterMsgs.PROCESS_REST_REQUEST, logFields, method, reqUrl, remoteHost, status); + } +} diff --git a/src/main/resources/auditservice_validation_schema.json b/src/main/resources/auditservice_validation_schema.json new file mode 100644 index 0000000..70d6845 --- /dev/null +++ b/src/main/resources/auditservice_validation_schema.json @@ -0,0 +1,20 @@ +{ + "fields": [ + {"name": "validationId", "data-type": "string", "searchable": "false"}, + {"name": "validationTimestamp", "data-type": "date", "format": "MMM d y HH:m:s||dd-MM-yyyy HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss.SSSZZ||MM\/dd\/yyyy||yyyyMMdd'T'HHmmssZ"}, + {"name": "modelVersionId", "data-type": "string"}, + {"name": "modelInvariantId", "data-type": "string"}, + {"name": "serviceInstanceId", "data-type": "string"}, + {"name": "result", "data-type": "string"}, + {"name": "violations", "data-type": "nested", "sub-fields": [ + {"name": "violationId", "data-type": "string", "searchable": "false"}, + {"name": "violationTimestamp", "data-type": "date", "format": "MMM d y HH:m:s||dd-MM-yyyy HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss.SSSZZ||MM\/dd\/yyyy||yyyyMMdd'T'HHmmssZ"}, + {"name": "modelName", "data-type": "string"}, + {"name": "category", "data-type": "string", "searchable": "false"}, + {"name": "severity", "data-type": "string", "searchable": "false"}, + {"name": "violationType", "data-type": "string", "searchable": "false"}, + {"name": "validationRule", "data-type": "string"}, + {"name": "errorMessage", "data-type": "string"} + ]} + ] +} \ No newline at end of file diff --git a/src/main/resources/auditservice_violation_schema.json b/src/main/resources/auditservice_violation_schema.json new file mode 100644 index 0000000..da88809 --- /dev/null +++ b/src/main/resources/auditservice_violation_schema.json @@ -0,0 +1,16 @@ +{ + "fields": [ + {"name": "validationId", "data-type": "string", "searchable": "false"}, + {"name": "validationTimestamp", "data-type": "date", "format": "MMM d y HH:m:s||dd-MM-yyyy HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss.SSSZZ||MM\/dd\/yyyy||yyyyMMdd'T'HHmmssZ"}, + {"name": "modelVersionId", "data-type": "string"}, + {"name": "modelInvariantId", "data-type": "string"}, + {"name": "serviceInstanceId", "data-type": "string"}, + {"name": "violationId", "data-type": "string", "searchable": "false"}, + {"name": "violationTimestamp", "data-type": "date", "format": "MMM d y HH:m:s||dd-MM-yyyy HH:mm:ss||yyyy-MM-dd'T'HH:mm:ss.SSSZZ||MM\/dd\/yyyy||yyyyMMdd'T'HHmmssZ"}, + {"name": "category", "data-type": "string", "searchable": "false"}, + {"name": "severity", "data-type": "string", "searchable": "false"}, + {"name": "violationType", "data-type": "string", "searchable": "false"}, + {"name": "validationRule", "data-type": "string"}, + {"name": "message", "data-type": "string"} + ] +} \ No newline at end of file diff --git a/src/main/resources/logging/ServiceIntegrityValidationsMsgs.properties b/src/main/resources/logging/ServiceIntegrityValidationsMsgs.properties new file mode 100644 index 0000000..c8fb270 --- /dev/null +++ b/src/main/resources/logging/ServiceIntegrityValidationsMsgs.properties @@ -0,0 +1,37 @@ +#Resource key=Error Code|Message text|Resolution text |Description text +####### +#Newlines can be utilized to add some clarity ensuring continuing line +#has atleast one leading space +#ResourceKey=\ +# ERR0000E\ +# Sample error msg txt\ +# Sample resolution msg\ +# Sample description txt +# +###### +#Error code classification category +#000 Info/Debug +#100 Permission errors +#200 Availability errors/Timeouts +#300 Data errors +#400 Schema Interface type/validation errors +#500 Business process errors +#900 Unknown errors +# +######################################################################## + +SI_POLICY_REGISTRATION=\ + SI0000I|\ + Service Integrity Validation policy successfully registered. + +SI_POLICY_DECISION=\ + SI0001I|\ + Service Integrity Validation policy resulted in {0}. {1} + +OPERATION_RESULT_ERRORS=\ + SI0002I|\ + Operation {0} completed in {1} ms with some errors + +DOCUMENT_STORE_PAYLOAD_FAILURE=\ + SI0301E|\ + Failed to store Service Integrity Violation event in Document Store. Policy payload: {0} with error: {1} \ No newline at end of file diff --git a/src/test/java/org/onap/aai/datarouter/entity/POAServiceInstanceEntityTest.java b/src/test/java/org/onap/aai/datarouter/entity/POAServiceInstanceEntityTest.java new file mode 100644 index 0000000..1f3db97 --- /dev/null +++ b/src/test/java/org/onap/aai/datarouter/entity/POAServiceInstanceEntityTest.java @@ -0,0 +1,281 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * 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.datarouter.entity; + +import static org.junit.Assert.assertEquals; + +import javax.ws.rs.core.Response.Status; +import org.junit.Assert; +import org.junit.Test; +import org.onap.aai.datarouter.exception.POAAuditException; + +public class POAServiceInstanceEntityTest { + + @Test + public void testPOAServiceInstanceEntity(){ + String svcInstanceId = "24602405-7714-4c64-81da-9e182a3eba59"; + String modelVersionId = "2f836857-d399-4de3-a6f8-e4a09d3017eb"; + String modelInvariantId = "8c383ba3-20c3-4196-b092-c8c007ef7ddc"; + String customerId = "global-customer-01"; + String serviceType = "vFW"; + String xFromAppId ="REST-client"; + String xTransactionId = "aaa111cccc4444"; + + POAServiceInstanceEntity svcEntity= new POAServiceInstanceEntity(); + svcEntity.setServiceInstanceId(svcInstanceId); + svcEntity.setModelVersionId(modelVersionId); + svcEntity.setModelInvariantId(modelInvariantId); + svcEntity.setCustomerId(customerId); + svcEntity.setServiceType(serviceType); + svcEntity.setxFromAppId(xFromAppId); + svcEntity.setxTransactionId(xTransactionId); + + Assert.assertEquals(svcInstanceId, svcEntity.getServiceInstanceId()); + Assert.assertEquals(modelVersionId, svcEntity.getModelVersionId()); + Assert.assertEquals(modelInvariantId, svcEntity.getModelInvariantId()); + + Assert.assertEquals(customerId, svcEntity.getCustomerId()); + Assert.assertEquals(serviceType, svcEntity.getServiceType()); + Assert.assertEquals(xFromAppId, svcEntity.getxFromAppId()); + Assert.assertEquals(xTransactionId, svcEntity.getxTransactionId()); + + } + + @Test + public void testNullServiceInstanceId() throws POAAuditException { + String modelVersionId = "2f836857-d399-4de3-a6f8-e4a09d3017eb"; + String modelInvariantId = "8c383ba3-20c3-4196-b092-c8c007ef7ddc"; + String customerId = "global-customer-01"; + String serviceType = "vFW"; + + POAServiceInstanceEntity svcEntity= new POAServiceInstanceEntity(); + svcEntity.setServiceInstanceId(null); + svcEntity.setModelVersionId(modelVersionId); + svcEntity.setModelInvariantId(modelInvariantId); + svcEntity.setCustomerId(customerId); + svcEntity.setServiceType(serviceType); + + try { + svcEntity.validate(); + } catch (POAAuditException e) { + assertEquals(Status.BAD_REQUEST, e.getHttpStatus()); + } + } + + + @Test + public void testEmptyServiceInstanceId() throws POAAuditException { + String modelVersionId = "2f836857-d399-4de3-a6f8-e4a09d3017eb"; + String modelInvariantId = "8c383ba3-20c3-4196-b092-c8c007ef7ddc"; + String customerId = "global-customer-01"; + String serviceType = "vFW"; + + POAServiceInstanceEntity svcEntity= new POAServiceInstanceEntity(); + svcEntity.setServiceInstanceId(""); + svcEntity.setModelVersionId(modelVersionId); + svcEntity.setModelInvariantId(modelInvariantId); + svcEntity.setCustomerId(customerId); + svcEntity.setServiceType(serviceType); + + try { + svcEntity.validate(); + } catch (POAAuditException e) { + assertEquals(Status.BAD_REQUEST, e.getHttpStatus()); + } + } + + + @Test + public void testNullModelVersionId() throws POAAuditException { + String svcInstanceId = "24602405-7714-4c64-81da-9e182a3eba59"; + String modelInvariantId = "8c383ba3-20c3-4196-b092-c8c007ef7ddc"; + String customerId = "global-customer-01"; + String serviceType = "vFW"; + + POAServiceInstanceEntity svcEntity= new POAServiceInstanceEntity(); + svcEntity.setServiceInstanceId(svcInstanceId); + svcEntity.setModelVersionId(null); + svcEntity.setModelInvariantId(modelInvariantId); + svcEntity.setCustomerId(customerId); + svcEntity.setServiceType(serviceType); + + try { + svcEntity.validate(); + } catch (POAAuditException e) { + assertEquals(Status.BAD_REQUEST, e.getHttpStatus()); + } + } + + @Test + public void testEmptyModelVersionId() throws POAAuditException { + String svcInstanceId = "24602405-7714-4c64-81da-9e182a3eba59"; + String modelInvariantId = "8c383ba3-20c3-4196-b092-c8c007ef7ddc"; + String customerId = "global-customer-01"; + String serviceType = "vFW"; + + POAServiceInstanceEntity svcEntity= new POAServiceInstanceEntity(); + svcEntity.setServiceInstanceId(svcInstanceId); + svcEntity.setModelVersionId(""); + svcEntity.setModelInvariantId(modelInvariantId); + svcEntity.setCustomerId(customerId); + svcEntity.setServiceType(serviceType); + + try { + svcEntity.validate(); + } catch (POAAuditException e) { + assertEquals(Status.BAD_REQUEST, e.getHttpStatus()); + } + } + + + @Test + public void testNullModelInvariantId() throws POAAuditException { + String svcInstanceId = "24602405-7714-4c64-81da-9e182a3eba59"; + String modelVersionId = "2f836857-d399-4de3-a6f8-e4a09d3017eb"; + String customerId = "global-customer-01"; + String serviceType = "vFW"; + + POAServiceInstanceEntity svcEntity= new POAServiceInstanceEntity(); + svcEntity.setServiceInstanceId(svcInstanceId); + svcEntity.setModelVersionId(modelVersionId); + svcEntity.setModelInvariantId(null); + svcEntity.setCustomerId(customerId); + svcEntity.setServiceType(serviceType); + + try { + svcEntity.validate(); + } catch (POAAuditException e) { + assertEquals(Status.BAD_REQUEST, e.getHttpStatus()); + } + } + + + @Test + public void testEmptyModelInvariantId() throws POAAuditException { + String svcInstanceId = "24602405-7714-4c64-81da-9e182a3eba59"; + String modelVersionId = "2f836857-d399-4de3-a6f8-e4a09d3017eb"; + String customerId = "global-customer-01"; + String serviceType = "vFW"; + + POAServiceInstanceEntity svcEntity= new POAServiceInstanceEntity(); + svcEntity.setServiceInstanceId(svcInstanceId); + svcEntity.setModelVersionId(modelVersionId); + svcEntity.setModelInvariantId(""); + svcEntity.setCustomerId(customerId); + svcEntity.setServiceType(serviceType); + + try { + svcEntity.validate(); + } catch (POAAuditException e) { + assertEquals(Status.BAD_REQUEST, e.getHttpStatus()); + } + } + + @Test + public void testNullServiceType() throws POAAuditException { + String svcInstanceId = "24602405-7714-4c64-81da-9e182a3eba59"; + String modelVersionId = "2f836857-d399-4de3-a6f8-e4a09d3017eb"; + String modelInvariantId = "8c383ba3-20c3-4196-b092-c8c007ef7ddc"; + String customerId = "global-customer-01"; + + + POAServiceInstanceEntity svcEntity= new POAServiceInstanceEntity(); + svcEntity.setServiceInstanceId(svcInstanceId); + svcEntity.setModelVersionId(modelVersionId); + svcEntity.setModelInvariantId(modelInvariantId); + svcEntity.setCustomerId(customerId); + svcEntity.setServiceType(null); + + try { + svcEntity.validate(); + } catch (POAAuditException e) { + assertEquals(Status.BAD_REQUEST, e.getHttpStatus()); + } + } + + + @Test + public void testEmptyServiceType() throws POAAuditException { + String svcInstanceId = "24602405-7714-4c64-81da-9e182a3eba59"; + String modelVersionId = "2f836857-d399-4de3-a6f8-e4a09d3017eb"; + String modelInvariantId = "8c383ba3-20c3-4196-b092-c8c007ef7ddc"; + String customerId = "global-customer-01"; + + + POAServiceInstanceEntity svcEntity= new POAServiceInstanceEntity(); + svcEntity.setServiceInstanceId(svcInstanceId); + svcEntity.setModelVersionId(modelVersionId); + svcEntity.setModelInvariantId(modelInvariantId); + svcEntity.setCustomerId(customerId); + svcEntity.setServiceType(""); + + try { + svcEntity.validate(); + } catch (POAAuditException e) { + assertEquals(Status.BAD_REQUEST, e.getHttpStatus()); + } + } + + + @Test + public void testNullCustomerId() throws POAAuditException { + String svcInstanceId = "24602405-7714-4c64-81da-9e182a3eba59"; + String modelVersionId = "2f836857-d399-4de3-a6f8-e4a09d3017eb"; + String modelInvariantId = "8c383ba3-20c3-4196-b092-c8c007ef7ddc"; + String serviceType = "vFW"; + + POAServiceInstanceEntity svcEntity= new POAServiceInstanceEntity(); + svcEntity.setServiceInstanceId(svcInstanceId); + svcEntity.setModelVersionId(modelVersionId); + svcEntity.setModelInvariantId(modelInvariantId); + svcEntity.setCustomerId(null); + svcEntity.setServiceType(serviceType); + + try { + svcEntity.validate(); + } catch (POAAuditException e) { + assertEquals(Status.BAD_REQUEST, e.getHttpStatus()); + } + } + + + @Test + public void testEmptyCustomerId() throws POAAuditException { + String svcInstanceId = "24602405-7714-4c64-81da-9e182a3eba59"; + String modelVersionId = "2f836857-d399-4de3-a6f8-e4a09d3017eb"; + String modelInvariantId = "8c383ba3-20c3-4196-b092-c8c007ef7ddc"; + String serviceType = "vFW"; + + POAServiceInstanceEntity svcEntity= new POAServiceInstanceEntity(); + svcEntity.setServiceInstanceId(svcInstanceId); + svcEntity.setModelVersionId(modelVersionId); + svcEntity.setModelInvariantId(modelInvariantId); + svcEntity.setCustomerId(""); + svcEntity.setServiceType(serviceType); + + try { + svcEntity.validate(); + } catch (POAAuditException e) { + assertEquals(Status.BAD_REQUEST, e.getHttpStatus()); + } + } + +} diff --git a/src/test/java/org/onap/aai/datarouter/exception/POAAuditExceptionTest.java b/src/test/java/org/onap/aai/datarouter/exception/POAAuditExceptionTest.java new file mode 100644 index 0000000..d5d4377 --- /dev/null +++ b/src/test/java/org/onap/aai/datarouter/exception/POAAuditExceptionTest.java @@ -0,0 +1,53 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * 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.datarouter.exception; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.junit.Assert; +import org.junit.Test; +import org.onap.aai.datarouter.logging.DataRouterMsgs; + +public class POAAuditExceptionTest { + + @Test + public void testPOAAuditExceptionWith400() { + String error = "Missing attribute: serviceInstanceId "; + + POAAuditException exception1 = new POAAuditException(error, Status.BAD_REQUEST, DataRouterMsgs.BAD_REST_REQUEST, error); + Assert.assertEquals(Response.Status.BAD_REQUEST, exception1.getHttpStatus()); + Assert.assertEquals(DataRouterMsgs.BAD_REST_REQUEST, exception1.getLogCode()); + } + + + @Test + public void testPOAAuditExceptionWith500() { + String error = "Failed to to create event publisher "; + String OPERATION = "POST to DMaaP"; + POAAuditException exception1 = new POAAuditException(error, Status.INTERNAL_SERVER_ERROR, DataRouterMsgs.EXCEPTION_DURING_METHOD_CALL, OPERATION); + + Assert.assertEquals(Response.Status.INTERNAL_SERVER_ERROR, exception1.getHttpStatus()); + Assert.assertEquals(DataRouterMsgs.EXCEPTION_DURING_METHOD_CALL, exception1.getLogCode()); + } + + +} diff --git a/src/test/java/org/onap/aai/datarouter/policy/ServiceIntegrityValidationPolicyStubbed.java b/src/test/java/org/onap/aai/datarouter/policy/ServiceIntegrityValidationPolicyStubbed.java new file mode 100644 index 0000000..163801f --- /dev/null +++ b/src/test/java/org/onap/aai/datarouter/policy/ServiceIntegrityValidationPolicyStubbed.java @@ -0,0 +1,67 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * 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.datarouter.policy; + + +public class ServiceIntegrityValidationPolicyStubbed extends ServiceIntegrityValidationPolicy{ + + private InMemorySearchDatastore searchDb; + + public ServiceIntegrityValidationPolicyStubbed(String searchCertPath, String searchCertTruststore, + String searchCertPassword, String searchBaseURL, String endpoint, String validationIndexName, + String violationIndexName) { + super(searchCertPath, searchCertTruststore, searchCertPassword, searchBaseURL, endpoint, validationIndexName, + violationIndexName); + + } + + + public InMemorySearchDatastore getSearchDb() { + return searchDb; + } + + + public ServiceIntegrityValidationPolicyStubbed withSearchDb(InMemorySearchDatastore searchDb) { + this.searchDb = searchDb; + return this; + } + + + public void handleSearchDataServiceOperation(String index, String id, String payload, String action) { + + //Stub out the actual call to Search Data service and instead store/update documents in memory + try { + switch (action.toLowerCase()) { + case "put": + searchDb.put(index, payload); // validation message + break; + case "post": + searchDb.put(index, payload); // violation message + break; + + default: + break; + } + } catch (Exception ex) { + } + + } +} diff --git a/src/test/java/org/onap/aai/datarouter/policy/ServiceIntegrityValidationPolicyTest.java b/src/test/java/org/onap/aai/datarouter/policy/ServiceIntegrityValidationPolicyTest.java new file mode 100644 index 0000000..0f0ee80 --- /dev/null +++ b/src/test/java/org/onap/aai/datarouter/policy/ServiceIntegrityValidationPolicyTest.java @@ -0,0 +1,112 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * 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.datarouter.policy; + +import static org.junit.Assert.*; +import static org.mockito.Matchers.anyObject; +import static org.mockito.Matchers.anyString; + +import java.io.File; +import java.io.FileInputStream; + +import org.apache.camel.Exchange; +import org.apache.camel.Message; +import org.apache.commons.io.IOUtils; +import org.junit.Before; +import org.junit.Test; +import org.onap.aai.datarouter.policy.EntityEventPolicy; +import org.onap.aai.datarouter.policy.EntityEventPolicyConfig; +import org.onap.aai.datarouter.util.NodeUtils; +import org.onap.aai.datarouter.util.SearchServiceAgent; +import org.powermock.api.mockito.PowerMockito; + + +public class ServiceIntegrityValidationPolicyTest { + private ServiceIntegrityValidationPolicy policy; + private String eventJson; + private String validationJson; + private String violationjson; + + private InMemorySearchDatastore searchDb; + + @SuppressWarnings("unchecked") + @Before + public void init() throws Exception { + + String searchCertPath = ""; + String searchCertTruststore =""; + String searchCertPassword = "password"; + String searchBaseURL = ""; + String endpoint = "services/search-data-service/v1/search/indexes/"; + String validationIndexName = "service-validations"; + String violationIndexName = "service-violations"; + + + searchDb = new InMemorySearchDatastore(); + policy = new ServiceIntegrityValidationPolicyStubbed(searchCertPath, searchCertTruststore, + searchCertPassword, searchBaseURL, endpoint, validationIndexName, violationIndexName).withSearchDb(searchDb); + + FileInputStream event = new FileInputStream( new File("src/test/resources/poa_audit_result.json")); + eventJson = IOUtils.toString(event, "UTF-8"); + + FileInputStream validation = new FileInputStream( new File("src/test/resources/poa_auditservice_validation.json")); + validationJson = IOUtils.toString(validation, "UTF-8"); + + FileInputStream violation = new FileInputStream( new File("src/test/resources/poa_auditservice_violation.json")); + violationjson = IOUtils.toString(violation, "UTF-8"); + + + } + + @Test + public void testProcess() throws Exception { + + policy.process(getExchangeEvent(validationJson)); + policy.process(getExchangeEvent(violationjson)); + + assertNotNull(searchDb.get("service-validations")); + assertNotNull(searchDb.get("service-violations")); + + } + + + + private Exchange getExchangeEvent(String outputJson){ + + Exchange exchange = PowerMockito.mock(Exchange.class); + Message inMessage = PowerMockito.mock(Message.class); + Message outMessage = PowerMockito.mock(Message.class); + PowerMockito.when(exchange.getIn()).thenReturn(inMessage); + PowerMockito.when(inMessage.getBody()).thenReturn(eventJson); + + PowerMockito.when(exchange.getOut()).thenReturn(outMessage); + PowerMockito.when(outMessage.getBody()).thenReturn(outputJson); + + PowerMockito.doNothing().when(outMessage).setBody(anyObject()); + PowerMockito.doNothing().when(outMessage).setHeader(anyString(), anyObject()); + + return exchange; + + } + + + +} diff --git a/src/test/java/org/onap/aai/datarouter/service/AuditServiceTest.java b/src/test/java/org/onap/aai/datarouter/service/AuditServiceTest.java new file mode 100644 index 0000000..334ff48 --- /dev/null +++ b/src/test/java/org/onap/aai/datarouter/service/AuditServiceTest.java @@ -0,0 +1,65 @@ +/** + * ============LICENSE_START======================================================= + * org.onap.aai + * ================================================================================ + * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017-2018 Amdocs + * ================================================================================ + * 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.datarouter.service; + +import static org.junit.Assert.assertEquals; + +import java.io.File; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.List; +import org.apache.commons.io.IOUtils; +import org.junit.Before; +import org.junit.Test; +import org.onap.aai.datarouter.entity.POAAuditEvent; +import org.onap.aai.datarouter.entity.POAServiceInstanceEntity; + + +public class AuditServiceTest { + + private String eventJson; + + + @Before + public void init() throws Exception { + FileInputStream event = new FileInputStream( new File("src/test/resources/poa_event.json")); + eventJson = IOUtils.toString(event, "UTF-8"); + } + + @Test + public void testPOAEvent() throws Exception { + + POAAuditEvent auditEvent = POAAuditEvent.fromJson(eventJson); + + List eventMessages = new ArrayList(); + for (POAServiceInstanceEntity serviceInstance: auditEvent.getServiceInstanceList()) { + serviceInstance.validate(); + serviceInstance.setxFromAppId("data-router"); + serviceInstance.setxTransactionId("111222888"); + eventMessages.add(serviceInstance.toJson()); + } + + assertEquals(2, eventMessages.size()); + } + + + +} diff --git a/src/test/resources/poa_audit_result.json b/src/test/resources/poa_audit_result.json new file mode 100644 index 0000000..aa48fec --- /dev/null +++ b/src/test/resources/poa_audit_result.json @@ -0,0 +1,336 @@ +{ + "validationId": "f825a232-b95b-425e-8ab0-bad4b913f770", + "validationTimestamp": "20180726T130520Z", + "entityType": "poa-entity", + "resourceVersion": null, + "violations": [ + { + "severity": "CRITICAL", + "modelName": null, + "violationType": "Rule", + "validationRule": "Verify AAI nf-naming-code", + "violationDetails": { + "context-list.aai.vf-list[*]": [ + { + "vnfc-list": [], + "name": "USBBBBmtwnjVVHP058", + "type": "HP", + "vf-module-list": [ + { + "min-instances": 0, + "max-instances": 1, + "uuid": "null", + "invariant-id": "null" + } + ] + } + ] + }, + "errorMessage": "The nf-naming-code is not populated in AAI VNF instance", + "category": "INVALID_VALUE", + "violationId": "b3ebe9ed846d3e1b07aad757cdd07cbec9d7012cab88d86889805b964cb70693" + }, + { + "severity": "INFO", + "modelName": null, + "violationType": "Rule", + "validationRule": "port-mirroring-AAI-vnfc-type-exists-in-SDC-SUCCESS", + "violationDetails": { + "context-list.aai.vf-list[*]": [ + { + "vnfc-list": [], + "name": "USBBBBmtwnjVVHP058", + "type": "HP", + "vf-module-list": [ + { + "min-instances": 0, + "max-instances": 1, + "uuid": "null", + "invariant-id": "null" + } + ] + } + ], + "context-list.sdc.vf-list[*]": [ + { + "vnfc-list": [ + { + "name": "IP_Mux_Demux", + "uuid": "85311c4a-e105-450e-9e54-756e9a3b3354", + "invariant-id": "ae2cbc96-5094-4fe6-9bd0-f87c56a92576" + } + ], + "name": "Pri_IP_Mux_Demux_7-27 0", + "type": "org.openecomp.resource.vf.IpMuxDemux727", + "uuid": "166c8608-a448-4413-8768-44bb2611f44b", + "invariant-id": "302b5f0c-f0c7-458e-a9f6-a4e49d40eba9", + "vf-module-list": [] + }, + { + "vnfc-list": [ + { + "name": "TEST", + "uuid": "14f2ee54-dc70-4193-af20-6c726897d3fa", + "invariant-id": "988b7048-4f46-4938-b6fd-b4e7ee1aec09" + } + ], + "name": "vHNF for SNIRO 0", + "type": "org.openecomp.resource.vf.VhnfForSniro", + "uuid": "68c00070-7f27-433b-b344-3b743e969039", + "invariant-id": "0c1522b2-fcd6-4718-8610-ed243ebb4659", + "vf-module-list": [ + { + "min-instances": 1, + "max-instances": 1, + "uuid": "1b6ccf7b-6217-45f7-a193-9f05422ddf35", + "invariant-id": "e428d1d8-3260-4ba8-9ca6-c400ee3ca085" + } + ] + }, + { + "vnfc-list": [ + { + "name": "Tunnel_XConn", + "uuid": "85311c4a-e105-450e-9e54-756e9a3b3354", + "invariant-id": "ae2cbc96-5094-4fe6-9bd0-f87c56a92576" + } + ], + "name": "Pri_Tunnel_XConn_7-27 0", + "type": "org.openecomp.resource.vf.TunnelXconn727", + "uuid": "1c05f81c-e2f1-4480-946e-56b01d8ef368", + "invariant-id": "d7db10ac-ed6e-456b-a57a-509384a3d70c", + "vf-module-list": [] + }, + { + "vnfc-list": [ + { + "name": "Tunnel_XConn", + "uuid": "85311c4a-e105-450e-9e54-756e9a3b3354", + "invariant-id": "ae2cbc96-5094-4fe6-9bd0-f87c56a92576" + } + ], + "name": "Sec_Tunnel_XConn_7-27 1", + "type": "org.openecomp.resource.vf.TunnelXconn727", + "uuid": "1c05f81c-e2f1-4480-946e-56b01d8ef368", + "invariant-id": "d7db10ac-ed6e-456b-a57a-509384a3d70c", + "vf-module-list": [] + }, + { + "vnfc-list": [ + { + "name": "service_admin", + "uuid": "85311c4a-e105-450e-9e54-756e9a3b3354", + "invariant-id": "ae2cbc96-5094-4fe6-9bd0-f87c56a92576" + } + ], + "name": "Sec_service_admin_7-27 1", + "type": "org.openecomp.resource.vf.ServiceAdmin727", + "uuid": "a02eaa28-62af-47ee-aac2-e66079a91a4d", + "invariant-id": "d39bf435-c760-4d42-9882-65371db9c7bb", + "vf-module-list": [] + }, + { + "vnfc-list": [ + { + "name": "IP_Mux_Demux", + "uuid": "85311c4a-e105-450e-9e54-756e9a3b3354", + "invariant-id": "ae2cbc96-5094-4fe6-9bd0-f87c56a92576" + } + ], + "name": "Sec_IP_Mux_Demux_7-27 1", + "type": "org.openecomp.resource.vf.IpMuxDemux727", + "uuid": "166c8608-a448-4413-8768-44bb2611f44b", + "invariant-id": "302b5f0c-f0c7-458e-a9f6-a4e49d40eba9", + "vf-module-list": [] + }, + { + "vnfc-list": [ + { + "name": "service_admin", + "uuid": "85311c4a-e105-450e-9e54-756e9a3b3354", + "invariant-id": "ae2cbc96-5094-4fe6-9bd0-f87c56a92576" + } + ], + "name": "Pri_service_admin_7-27 0", + "type": "org.openecomp.resource.vf.ServiceAdmin727", + "uuid": "a02eaa28-62af-47ee-aac2-e66079a91a4d", + "invariant-id": "d39bf435-c760-4d42-9882-65371db9c7bb", + "vf-module-list": [] + } + ] + }, + "errorMessage": "Every vnfc type specified in sdc has been created in AAI", + "category": "SUCCESS", + "violationId": "bfe9ba434a231a0bd263f0753c517fc503639fc5210847f61c591e98e6dafbfa" + } + ], + "entityId": { + + }, + "entityLink": "", + "entity": { + "poa-event": { + "serviceType": "HNPORTAL", + "modelVersionId": "f8cd30d9-6583-4cc9-8b41-48ca67689ba1", + "modelInvariantId": "b4b1177c-4b1f-48b9-85fd-a57804df88ce", + "customerId": "21014aa2-526b-11e6-beb8-9e71128cae77", + "serviceInstanceId": "6133b7a8-da74-40c5-8a67-b458e0c0beb7", + "xTransactionId": "2309039=x", + "xFromAppId": "Data-Router" + }, + "context-list": { + "sdc": { + "vf-list": [ + { + "vnfc-list": [ + { + "name": "IP_Mux_Demux", + "uuid": "85311c4a-e105-450e-9e54-756e9a3b3354", + "invariant-id": "ae2cbc96-5094-4fe6-9bd0-f87c56a92576" + } + ], + "name": "Pri_IP_Mux_Demux_7-27 0", + "type": "org.openecomp.resource.vf.IpMuxDemux727", + "uuid": "166c8608-a448-4413-8768-44bb2611f44b", + "invariant-id": "302b5f0c-f0c7-458e-a9f6-a4e49d40eba9", + "vf-module-list": [] + }, + { + "vnfc-list": [ + { + "name": "TEST", + "uuid": "14f2ee54-dc70-4193-af20-6c726897d3fa", + "invariant-id": "988b7048-4f46-4938-b6fd-b4e7ee1aec09" + } + ], + "name": "vHNF for SNIRO 0", + "type": "org.openecomp.resource.vf.VhnfForSniro", + "uuid": "68c00070-7f27-433b-b344-3b743e969039", + "invariant-id": "0c1522b2-fcd6-4718-8610-ed243ebb4659", + "vf-module-list": [ + { + "min-instances": 1, + "max-instances": 1, + "uuid": "1b6ccf7b-6217-45f7-a193-9f05422ddf35", + "invariant-id": "e428d1d8-3260-4ba8-9ca6-c400ee3ca085" + } + ] + }, + { + "vnfc-list": [ + { + "name": "Tunnel_XConn", + "uuid": "85311c4a-e105-450e-9e54-756e9a3b3354", + "invariant-id": "ae2cbc96-5094-4fe6-9bd0-f87c56a92576" + } + ], + "name": "Pri_Tunnel_XConn_7-27 0", + "type": "org.openecomp.resource.vf.TunnelXconn727", + "uuid": "1c05f81c-e2f1-4480-946e-56b01d8ef368", + "invariant-id": "d7db10ac-ed6e-456b-a57a-509384a3d70c", + "vf-module-list": [] + }, + { + "vnfc-list": [ + { + "name": "Tunnel_XConn", + "uuid": "85311c4a-e105-450e-9e54-756e9a3b3354", + "invariant-id": "ae2cbc96-5094-4fe6-9bd0-f87c56a92576" + } + ], + "name": "Sec_Tunnel_XConn_7-27 1", + "type": "org.openecomp.resource.vf.TunnelXconn727", + "uuid": "1c05f81c-e2f1-4480-946e-56b01d8ef368", + "invariant-id": "d7db10ac-ed6e-456b-a57a-509384a3d70c", + "vf-module-list": [] + }, + { + "vnfc-list": [ + { + "name": "service_admin", + "uuid": "85311c4a-e105-450e-9e54-756e9a3b3354", + "invariant-id": "ae2cbc96-5094-4fe6-9bd0-f87c56a92576" + } + ], + "name": "Sec_service_admin_7-27 1", + "type": "org.openecomp.resource.vf.ServiceAdmin727", + "uuid": "a02eaa28-62af-47ee-aac2-e66079a91a4d", + "invariant-id": "d39bf435-c760-4d42-9882-65371db9c7bb", + "vf-module-list": [] + }, + { + "vnfc-list": [ + { + "name": "IP_Mux_Demux", + "uuid": "85311c4a-e105-450e-9e54-756e9a3b3354", + "invariant-id": "ae2cbc96-5094-4fe6-9bd0-f87c56a92576" + } + ], + "name": "Sec_IP_Mux_Demux_7-27 1", + "type": "org.openecomp.resource.vf.IpMuxDemux727", + "uuid": "166c8608-a448-4413-8768-44bb2611f44b", + "invariant-id": "302b5f0c-f0c7-458e-a9f6-a4e49d40eba9", + "vf-module-list": [] + }, + { + "vnfc-list": [ + { + "name": "service_admin", + "uuid": "85311c4a-e105-450e-9e54-756e9a3b3354", + "invariant-id": "ae2cbc96-5094-4fe6-9bd0-f87c56a92576" + } + ], + "name": "Pri_service_admin_7-27 0", + "type": "org.openecomp.resource.vf.ServiceAdmin727", + "uuid": "a02eaa28-62af-47ee-aac2-e66079a91a4d", + "invariant-id": "d39bf435-c760-4d42-9882-65371db9c7bb", + "vf-module-list": [] + } + ], + "service": { + "name": "SD-WAN_7-27", + "uuid": "f8cd30d9-6583-4cc9-8b41-48ca67689ba1", + "invariant-id": "b4b1177c-4b1f-48b9-85fd-a57804df88ce" + } + }, + "sdnc": { + "vf-list": [ + { + "vnfc-list": [], + "name": "null", + "type": "null", + "uuid": "null", + "invariant-id": "null", + "vf-module-list": [] + } + ], + "service": { + "name": "null", + "uuid": "null", + "invariant-id": "null" + } + }, + "aai": { + "vf-list": [ + { + "vnfc-list": [], + "name": "USBBBBmtwnjVVHP058", + "type": "HP", + "vf-module-list": [ + { + "min-instances": 0, + "max-instances": 1, + "uuid": "null", + "invariant-id": "null" + } + ] + } + ], + "service": { + "uuid": "f8cd30d9-6583-4cc9-8b41-48ca67689ba1", + "invariant-id": "b4b1177c-4b1f-48b9-85fd-a57804df88ce" + } + } + } + } +} \ No newline at end of file diff --git a/src/test/resources/poa_auditservice_validation.json b/src/test/resources/poa_auditservice_validation.json new file mode 100644 index 0000000..68c7363 --- /dev/null +++ b/src/test/resources/poa_auditservice_validation.json @@ -0,0 +1,27 @@ +{ + "violations": [ + { + "severity": "CRITICAL", + "modelName": "string", + "violationType": "Rule", + "validationRule": "Default rule: Validate that vnf-type AAI VF instance matches vnf-type in SDN-C", + "errorMessage": "The vnf-type AAI VF instance does not match vnf-type in SDN-C", + "category": "INVALID_VALUE", + "violationId": "8b601abb25d5a1de57f18a76dfe387acfe5d3a80b808b536f9a87bd26cad4839" + }, + { + "severity": "CRITICAL", + "modelName": "string ", + "violationType": "Rule", + "validationRule": "Default rule: Validate that vnf-name AAI VF instance matches vnf-name in SDN-C", + "errorMessage": "The vnf-name AAI VF instance does not match vnf-name in SDN-C", + "category": "INVALID_VALUE", + "violationId": "21ea7130f41b60b8611682fdfb7155706728b2b8d9b7152a7fcc976ae28fe31c" + } + ], + "validationId": "648c9c29-d820-483b-848e-7cb99a8c1281", + "validationTimestamp": "20180726T184111Z", + "modelVersionId": "f9f9a036-ee93-4d92-b779-a533463dba01", + "modelInvariantId": "726625ea-62be-4fe6-af5b-07862919232f", + "serviceInstanceId": "617745d3-1ccb-49f1-94ee-2d1aec00ff68" +} \ No newline at end of file diff --git a/src/test/resources/poa_auditservice_violation.json b/src/test/resources/poa_auditservice_violation.json new file mode 100644 index 0000000..31320e3 --- /dev/null +++ b/src/test/resources/poa_auditservice_violation.json @@ -0,0 +1,14 @@ +{ + "validationId": "b65a3abf-c95a-4917-bf70-50f588dc4c09", + "validationTimestamp": "20180531T161324Z", + "modelVersionId": "e9851a43-c068-4eb2-9fe7-2d123bd94ff0", + "modelInvariantId": "4fd21763-23ed-4f69-8654-e121626df327", + "serviceInstanceId": "b06270ab-99e6-4a58-9bc0-db2df5c36f4d", + "violationId": "596314f8158658eed4e12991b87409e21b57818cd62c2e6da4c42a61b3b9c29c", + "violationTimestamp": "20180724T161324Z", + "category": "INVALID_VALUE", + "severity": "CRITICAL", + "violationType": "Rule", + "validationRule": "Default rule: Validate that vnf-type AAI VF instance matches vnf-type in SDN-C", + "message": "The vnf-type AAI VF instance does not match vnf-type in SDN-C" +} \ No newline at end of file diff --git a/src/test/resources/poa_event.json b/src/test/resources/poa_event.json new file mode 100644 index 0000000..c46d941 --- /dev/null +++ b/src/test/resources/poa_event.json @@ -0,0 +1,18 @@ +{ + "serviceInstanceList": [ + { + "serviceInstanceId": "24602405-7714-4c64-81da-9e182a3eba59", + "modelVersionId": "2f836857-d399-4de3-a6f8-e4a09d3017eb", + "modelInvariantId": "8c383ba3-20c3-4196-b092-c8c007ef7ddc", + "serviceType": "Mobility", + "customerId": "some.customer.id1" + }, + { + "serviceInstanceId": "1111-744444-4c64-81da-9e182a3eba59", + "modelVersionId": "3333dfef836857-d399-4de3-a6f8-e4a09d3017eb", + "modelInvariantId": "7c5tba-20c3-4196-b092-c8c007ef7ddc", + "serviceType": "some.service.type", + "customerId": "some.customer.id2" + } + ] +} \ No newline at end of file -- 2.16.6