From adb2ad2d16e851fbf8dcc71af68949a74463204d Mon Sep 17 00:00:00 2001 From: efiacor Date: Wed, 23 Oct 2019 15:31:43 +0100 Subject: [PATCH] More bug fix and refactoring Signed-off-by: efiacor Change-Id: I4fce4e73faa86573d0c716882bb014b9f83026ee Issue-ID: DMAAP-1284 --- datarouter-node/pom.xml | 4 +- .../org/onap/dmaap/datarouter/node/Delivery.java | 1 - .../onap/dmaap/datarouter/node/DeliveryQueue.java | 13 +- .../dmaap/datarouter/node/NodeAafPropsUtils.java | 2 +- .../dmaap/datarouter/node/NodeConfigManager.java | 210 ++-- .../org/onap/dmaap/datarouter/node/NodeMain.java | 189 ---- .../org/onap/dmaap/datarouter/node/NodeRunner.java | 96 ++ .../org/onap/dmaap/datarouter/node/NodeServer.java | 147 +++ .../onap/dmaap/datarouter/node/NodeServlet.java | 2 +- .../src/main/resources/docker/startup.sh | 2 +- datarouter-node/src/main/resources/misc/drtrnode | 2 +- .../dmaap/datarouter/node/DeliveryTaskTest.java | 21 +- .../dmaap/datarouter/node/LogbackFilterTest.java | 3 +- .../datarouter/node/NodeAafPropsUtilsTest.java | 14 +- .../datarouter/node/NodeConfigManagerTest.java | 99 +- .../onap/dmaap/datarouter/node/NodeServerTest.java | 119 +++ .../dmaap/datarouter/node/NodeServletTest.java | 8 +- .../resources/aaf/org.onap.dmaap-dr.cred.props | 2 +- .../test/resources/aaf/org.onap.dmaap-dr.trust.jks | Bin 0 -> 1413 bytes datarouter-node/src/test/resources/prov_data.json | 129 +++ datarouter-prov/pom.xml | 2 +- .../dmaap/datarouter/provisioning/ProvRunner.java | 208 +--- .../dmaap/datarouter/provisioning/ProvServer.java | 236 +++++ .../datarouter/provisioning/ProxyServlet.java | 4 - .../datarouter/provisioning/beans/EgressRoute.java | 9 +- .../datarouter/provisioning/beans/Parameters.java | 11 +- .../provisioning/utils/AafPropsUtils.java | 21 +- .../datarouter/provisioning/utils/DRRouteCLI.java | 1011 ++++++++++---------- datarouter-prov/src/main/resources/logback.xml | 6 +- .../datarouter/provisioning/ProvServerTest.java | 57 ++ .../provisioning/utils/AafPropsUtilsTest.java | 3 +- .../src/test/resources/aaf/org.onap.dmaap-dr.p12 | Bin 0 -> 4233 bytes .../test/resources/aaf/org.onap.dmaap-dr.trust.jks | Bin 0 -> 1413 bytes .../src/test/resources/h2Database.properties | 1 + datarouter-prov/src/test/resources/prov_data.json | 2 +- 35 files changed, 1567 insertions(+), 1067 deletions(-) delete mode 100644 datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeMain.java create mode 100644 datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeRunner.java create mode 100644 datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeServer.java create mode 100644 datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeServerTest.java create mode 100644 datarouter-node/src/test/resources/aaf/org.onap.dmaap-dr.trust.jks create mode 100644 datarouter-node/src/test/resources/prov_data.json create mode 100644 datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/ProvServer.java create mode 100644 datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/ProvServerTest.java create mode 100644 datarouter-prov/src/test/resources/aaf/org.onap.dmaap-dr.p12 create mode 100644 datarouter-prov/src/test/resources/aaf/org.onap.dmaap-dr.trust.jks diff --git a/datarouter-node/pom.xml b/datarouter-node/pom.xml index af605b0b..d9650c23 100755 --- a/datarouter-node/pom.xml +++ b/datarouter-node/pom.xml @@ -234,7 +234,7 @@ true - org.onap.dmaap.datarouter.node.NodeMain + org.onap.dmaap.datarouter.node.NodeRunner @@ -355,7 +355,7 @@ jacoco-maven-plugin - src/main/java/org/onap/dmaap/datarouter/node/NodeMain.java + src/main/java/org/onap/dmaap/datarouter/node/NodeRunner.java diff --git a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/Delivery.java b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/Delivery.java index 83d5186a..59318563 100644 --- a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/Delivery.java +++ b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/Delivery.java @@ -66,7 +66,6 @@ public class Delivery { this.config = config; Runnable cmon = this::checkconfig; config.registerConfigTask(cmon); - checkconfig(); } /** diff --git a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/DeliveryQueue.java b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/DeliveryQueue.java index 4d336b73..d447bcc1 100644 --- a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/DeliveryQueue.java +++ b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/DeliveryQueue.java @@ -224,16 +224,13 @@ public class DeliveryQueue implements Runnable, DeliveryTaskHelper { todoindex = 0; todoList = new ArrayList<>(); String[] files = dir.list(); - Arrays.sort(files); - scanForNextTask(files); + if (files != null) { + Arrays.sort(files); + scanForNextTask(files); + } retry = new HashMap<>(); } - DeliveryTask dt = getDeliveryTask(mindate); - if (dt != null) { - return dt; - } - return null; - + return getDeliveryTask(mindate); } } diff --git a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeAafPropsUtils.java b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeAafPropsUtils.java index 542dfd08..0c31db99 100644 --- a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeAafPropsUtils.java +++ b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeAafPropsUtils.java @@ -45,7 +45,7 @@ class NodeAafPropsUtils { String getDecryptedPass(String password) { String decryptedPass = ""; try { - decryptedPass = getPropAccess().decrypt(getPropAccess().getProperty(password), false); + decryptedPass = propAccess.decrypt(propAccess.getProperty(password), false); } catch (IOException e) { eelfLogger.error("Failed to decrypt " + password + " : " + e.getMessage(), e); } diff --git a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeConfigManager.java b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeConfigManager.java index aeddc729..298e1858 100644 --- a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeConfigManager.java +++ b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeConfigManager.java @@ -53,7 +53,6 @@ import org.onap.dmaap.datarouter.node.eelf.EelfMsgs; */ public class NodeConfigManager implements DeliveryQueueHelper { - private static final String CHANGE_ME = "changeme"; private static final String NODE_CONFIG_MANAGER = "NodeConfigManager"; private static EELFLogger eelfLogger = EELFManager.getInstance().getLogger(NodeConfigManager.class); private static NodeConfigManager base = new NodeConfigManager(); @@ -103,7 +102,6 @@ public class NodeConfigManager implements DeliveryQueueHelper { private String aafType; private String aafInstance; private String aafAction; - private String aafURL; private boolean cadiEnabled; private NodeAafPropsUtils nodeAafPropsUtils; @@ -141,7 +139,6 @@ public class NodeConfigManager implements DeliveryQueueHelper { aafInstance = drNodeProperties.getProperty("AAFInstance", "legacy"); aafAction = drNodeProperties.getProperty("AAFAction", "publish"); cadiEnabled = Boolean.parseBoolean(drNodeProperties.getProperty("CadiEnabled", "false")); - aafURL = nodeAafPropsUtils.getPropAccess().getProperty("aaf_locate_url", "https://aaf-locate:8095"); /* * END - AAF changes: TDP EPIC US# 307413 * Pull AAF settings from node.properties @@ -300,7 +297,8 @@ public class NodeConfigManager implements DeliveryQueueHelper { private void fetchconfig() { try { eelfLogger.debug("NodeConfigMan.fetchConfig: provurl:: " + provurl); - Reader reader = new InputStreamReader((new URL(provurl)).openStream()); + URL url = new URL(provurl); + Reader reader = new InputStreamReader(url.openStream()); config = new NodeConfig(new ProvData(reader), myname, spooldir, port, nak); localconfig(); configtasks.startRun(); @@ -329,7 +327,7 @@ public class NodeConfigManager implements DeliveryQueueHelper { * fetch the provisioning data, ignore the request. If the data has been fetched very recently (default 10 * seconds), wait a while before fetching again. */ - public synchronized void gofetch(String remoteAddr) { + synchronized void gofetch(String remoteAddr) { if (provcheck.isReachable(remoteAddr)) { eelfLogger.debug("NODE0307 Received configuration fetch request from provisioning server " + remoteAddr); pfetcher.request(); @@ -341,15 +339,15 @@ public class NodeConfigManager implements DeliveryQueueHelper { /** * Am I configured. */ - public boolean isConfigured() { - return (config != null); + boolean isConfigured() { + return config != null; } /** * Am I shut down. */ - public boolean isShutdown() { - return (quiesce.exists()); + boolean isShutdown() { + return quiesce.exists(); } /** @@ -358,8 +356,8 @@ public class NodeConfigManager implements DeliveryQueueHelper { * @param routing Target string * @return array of targets */ - public Target[] parseRouting(String routing) { - return (config.parseRouting(routing)); + Target[] parseRouting(String routing) { + return config.parseRouting(routing); } /** @@ -369,8 +367,8 @@ public class NodeConfigManager implements DeliveryQueueHelper { * @param ip IP address the request came from * @return If the credentials and IP address are recognized, true, otherwise false. */ - public boolean isAnotherNode(String credentials, String ip) { - return (config.isAnotherNode(credentials, ip)); + boolean isAnotherNode(String credentials, String ip) { + return config.isAnotherNode(credentials, ip); } /** @@ -381,8 +379,8 @@ public class NodeConfigManager implements DeliveryQueueHelper { * @param ip The requesting IP address * @return True if the IP and credentials are valid for the specified feed. */ - public String isPublishPermitted(String feedid, String credentials, String ip) { - return (config.isPublishPermitted(feedid, credentials, ip)); + String isPublishPermitted(String feedid, String credentials, String ip) { + return config.isPublishPermitted(feedid, credentials, ip); } /** @@ -392,8 +390,8 @@ public class NodeConfigManager implements DeliveryQueueHelper { * @param ip The requesting IP address * @return True if the IP and credentials are valid for the specified feed. */ - public String isPublishPermitted(String feedid, String ip) { - return (config.isPublishPermitted(feedid, ip)); + String isPublishPermitted(String feedid, String ip) { + return config.isPublishPermitted(feedid, ip); } /** @@ -402,8 +400,8 @@ public class NodeConfigManager implements DeliveryQueueHelper { * @param subId The ID of the subscription being requested * @return True if the delete file is permitted for the subscriber. */ - public boolean isDeletePermitted(String subId) { - return (config.isDeletePermitted(subId)); + boolean isDeletePermitted(String subId) { + return config.isDeletePermitted(subId); } /** @@ -413,8 +411,8 @@ public class NodeConfigManager implements DeliveryQueueHelper { * @param credentials The offered credentials * @return Null if the credentials are invalid or the user if they are valid. */ - public String getAuthUser(String feedid, String credentials) { - return (config.getAuthUser(feedid, credentials)); + String getAuthUser(String feedid, String credentials) { + return config.getAuthUser(feedid, credentials); } /** @@ -422,11 +420,11 @@ public class NodeConfigManager implements DeliveryQueueHelper { * * @param feedid The ID of the feed specified */ - public String getAafInstance(String feedid) { - return (config.getAafInstance(feedid)); + String getAafInstance(String feedid) { + return config.getAafInstance(feedid); } - public String getAafInstance() { + String getAafInstance() { return aafInstance; } @@ -438,8 +436,8 @@ public class NodeConfigManager implements DeliveryQueueHelper { * @param ip The IP address of the publish endpoint * @return Null if the request should be accepted or the correct hostname if it should be sent to another node. */ - public String getIngressNode(String feedid, String user, String ip) { - return (config.getIngressNode(feedid, user, ip)); + String getIngressNode(String feedid, String user, String ip) { + return config.getIngressNode(feedid, user, ip); } /** @@ -448,8 +446,8 @@ public class NodeConfigManager implements DeliveryQueueHelper { * @param name The name of the parameter * @return The value of the parameter or null if it is not defined. */ - public String getProvParam(String name) { - return (config.getProvParam(name)); + private String getProvParam(String name) { + return config.getProvParam(name); } /** @@ -459,39 +457,39 @@ public class NodeConfigManager implements DeliveryQueueHelper { * @param defaultValue The value to use if the parameter is not defined * @return The value of the parameter or deflt if it is not defined. */ - public String getProvParam(String name, String defaultValue) { + private String getProvParam(String name, String defaultValue) { name = config.getProvParam(name); if (name == null) { name = defaultValue; } - return (name); + return name; } /** * Generate a publish ID. */ public String getPublishId() { - return (pid.next()); + return pid.next(); } /** * Get all the outbound spooling destinations. This will include both subscriptions and nodes. */ - public DestInfo[] getAllDests() { - return (config.getAllDests()); + DestInfo[] getAllDests() { + return config.getAllDests(); } /** * Register a task to run whenever the configuration changes. */ - public void registerConfigTask(Runnable task) { + void registerConfigTask(Runnable task) { configtasks.addTask(task); } /** * Deregister a task to run whenever the configuration changes. */ - public void deregisterConfigTask(Runnable task) { + void deregisterConfigTask(Runnable task) { configtasks.removeTask(task); } @@ -542,49 +540,49 @@ public class NodeConfigManager implements DeliveryQueueHelper { * Get the timeout before retrying after an initial delivery failure. */ public long getInitFailureTimer() { - return (initfailuretimer); + return initfailuretimer; } /** * Get the timeout before retrying after delivery and wait for file processing. */ public long getWaitForFileProcessFailureTimer() { - return (waitForFileProcessFailureTimer); + return waitForFileProcessFailureTimer; } /** * Get the maximum timeout between delivery attempts. */ public long getMaxFailureTimer() { - return (maxfailuretimer); + return maxfailuretimer; } /** * Get the ratio between consecutive delivery attempts. */ public double getFailureBackoff() { - return (failurebackoff); + return failurebackoff; } /** * Get the expiration timer for deliveries. */ public long getExpirationTimer() { - return (expirationtimer); + return expirationtimer; } /** * Get the maximum number of file delivery attempts before checking if another queue has work to be performed. */ public int getFairFileLimit() { - return (fairfilelimit); + return fairfilelimit; } /** * Get the maximum amount of time spent delivering files before checking if another queue has work to be performed. */ public long getFairTimeLimit() { - return (fairtimelimit); + return fairtimelimit; } /** @@ -593,21 +591,21 @@ public class NodeConfigManager implements DeliveryQueueHelper { * @param feedid The feed ID * @return The targets this feed should be delivered to */ - public Target[] getTargets(String feedid) { - return (config.getTargets(feedid)); + Target[] getTargets(String feedid) { + return config.getTargets(feedid); } /** * Get the spool directory for temporary files. */ - public String getSpoolDir() { - return (spooldir + "/f"); + String getSpoolDir() { + return spooldir + "/f"; } /** * Get the spool directory for a subscription. */ - public String getSpoolDir(String subid, String remoteaddr) { + String getSpoolDir(String subid, String remoteaddr) { if (provcheck.isFrom(remoteaddr)) { String sdir = config.getSpoolDir(subid); if (sdir != null) { @@ -617,137 +615,150 @@ public class NodeConfigManager implements DeliveryQueueHelper { eelfLogger.debug("NODE0311 Received subscription reset request for unknown subscription " + subid + " from provisioning server " + remoteaddr); } - return (sdir); + return sdir; } else { eelfLogger.debug("NODE0312 Received subscription reset request from unexpected server " + remoteaddr); - return (null); + return null; } } /** * Get the base directory for spool directories. */ - public String getSpoolBase() { - return (spooldir); + String getSpoolBase() { + return spooldir; } /** * Get the key store type. */ - public String getKSType() { - return (kstype); + String getKSType() { + return kstype; } /** * Get the key store file. */ - public String getKSFile() { - return (ksfile); + String getKSFile() { + return ksfile; } /** * Get the key store password. */ - public String getKSPass() { - return (kspass); + String getKSPass() { + return kspass; } /** * Get the key password. */ - public String getKPass() { - return (kpass); + String getKPass() { + return kpass; + } + + + String getTstype() { + return tstype; + } + + String getTsfile() { + return tsfile; + } + + String getTspass() { + return tspass; } /** * Get the http port. */ - public int getHttpPort() { - return (gfport); + int getHttpPort() { + return gfport; } /** * Get the https port. */ - public int getHttpsPort() { - return (svcport); + int getHttpsPort() { + return svcport; } /** * Get the externally visible https port. */ - public int getExtHttpsPort() { - return (port); + int getExtHttpsPort() { + return port; } /** * Get the external name of this machine. */ - public String getMyName() { - return (myname); + String getMyName() { + return myname; } /** * Get the number of threads to use for delivery. */ - public int getDeliveryThreads() { - return (deliverythreads); + int getDeliveryThreads() { + return deliverythreads; } /** * Get the URL for uploading the event log data. */ - public String getEventLogUrl() { - return (eventlogurl); + String getEventLogUrl() { + return eventlogurl; } /** * Get the prefix for the names of event log files. */ - public String getEventLogPrefix() { - return (eventlogprefix); + String getEventLogPrefix() { + return eventlogprefix; } /** * Get the suffix for the names of the event log files. */ - public String getEventLogSuffix() { - return (eventlogsuffix); + String getEventLogSuffix() { + return eventlogsuffix; } /** * Get the interval between event log file rollovers. */ - public String getEventLogInterval() { - return (eventloginterval); + String getEventLogInterval() { + return eventloginterval; } /** * Should I follow redirects from subscribers. */ public boolean isFollowRedirects() { - return (followredirects); + return followredirects; } /** * Get the directory where the event and node log files live. */ - public String getLogDir() { - return (logdir); + String getLogDir() { + return logdir; } /** * How long do I keep log files (in milliseconds). */ - public long getLogRetention() { - return (logretention); + long getLogRetention() { + return logretention; } /** * Get the timer. */ public Timer getTimer() { - return (timer); + return timer; } /** @@ -757,7 +768,7 @@ public class NodeConfigManager implements DeliveryQueueHelper { * @return The feed ID */ public String getFeedId(String subid) { - return (config.getFeedId(subid)); + return config.getFeedId(subid); } /** @@ -765,53 +776,46 @@ public class NodeConfigManager implements DeliveryQueueHelper { * * @return The Authorization string for this node */ - public String getMyAuth() { - return (config.getMyAuth()); + String getMyAuth() { + return config.getMyAuth(); } /** * Get the fraction of free spool disk space where we start throwing away undelivered files. This is * FREE_DISK_RED_PERCENT / 100.0. Default is 0.05. Limited by 0.01 <= FreeDiskStart <= 0.5. */ - public double getFreeDiskStart() { - return (fdpstart); + double getFreeDiskStart() { + return fdpstart; } /** * Get the fraction of free spool disk space where we stop throwing away undelivered files. This is * FREE_DISK_YELLOW_PERCENT / 100.0. Default is 0.2. Limited by FreeDiskStart <= FreeDiskStop <= 0.5. */ - public double getFreeDiskStop() { - return (fdpstop); + double getFreeDiskStop() { + return fdpstop; } /** * Disable and enable protocols. */ - public String[] getEnabledprotocols() { + String[] getEnabledprotocols() { return enabledprotocols; } - public String getAafType() { + String getAafType() { return aafType; } - public String getAafAction() { + String getAafAction() { return aafAction; } - /* - * Get aafURL from SWM variable - * */ - public String getAafURL() { - return aafURL; - } - - public boolean getCadiEnabled() { + boolean getCadiEnabled() { return cadiEnabled; } - public NodeAafPropsUtils getNodeAafPropsUtils() { + NodeAafPropsUtils getNodeAafPropsUtils() { return nodeAafPropsUtils; } @@ -821,7 +825,7 @@ public class NodeConfigManager implements DeliveryQueueHelper { * @param aafInstance The aaf instance * @return The permissions */ - protected String getPermission(String aafInstance) { + String getPermission(String aafInstance) { try { String type = getAafType(); String action = getAafAction(); diff --git a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeMain.java b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeMain.java deleted file mode 100644 index 56086301..00000000 --- a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeMain.java +++ /dev/null @@ -1,189 +0,0 @@ -/******************************************************************************* - * ============LICENSE_START================================================== - * * org.onap.dmaap - * * =========================================================================== - * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * * =========================================================================== - * * Licensed under the Apache License, Version 2.0 (the "License"); - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * - * * http://www.apache.org/licenses/LICENSE-2.0 - * * - * * Unless required by applicable law or agreed to in writing, software - * * distributed under the License is distributed on an "AS IS" BASIS, - * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * * See the License for the specific language governing permissions and - * * limitations under the License. - * * ============LICENSE_END==================================================== - * * - * * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * * - ******************************************************************************/ - -package org.onap.dmaap.datarouter.node; - -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; -import java.util.EnumSet; -import javax.servlet.DispatcherType; -import org.eclipse.jetty.http.HttpVersion; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpConnectionFactory; -import org.eclipse.jetty.server.SecureRequestCustomizer; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.SslConnectionFactory; -import org.eclipse.jetty.servlet.FilterHolder; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.ssl.SslContextFactory; - -/** - * The main starting point for the Data Router node. - */ -public class NodeMain { - - private static EELFLogger nodeMainLogger = EELFManager.getInstance().getLogger(NodeMain.class); - private static Delivery delivery; - private static NodeConfigManager nodeConfigManager; - - private NodeMain() { - } - - /** - * Reset the retry timer for a subscription. - */ - - static void resetQueue(String subid, String ip) { - delivery.resetQueue(nodeConfigManager.getSpoolDir(subid, ip)); - } - - /** - * Start the data router. - * - *

The location of the node configuration file can be set using the org.onap.dmaap.datarouter.node.properties - * system property. By default, it is "/opt/app/datartr/etc/node.properties". - */ - public static void main(String[] args) throws Exception { - nodeMainLogger.debug("NODE0001 Data Router Node Starting"); - IsFrom.setDNSCache(); - nodeConfigManager = NodeConfigManager.getInstance(); - nodeMainLogger.debug("NODE0002 I am " + nodeConfigManager.getMyName()); - (new WaitForConfig(nodeConfigManager)).waitForConfig(); - delivery = new Delivery(nodeConfigManager); - new LogManager(nodeConfigManager); - - Server server = new Server(); - - // HTTP configuration - HttpConfiguration httpConfiguration = new HttpConfiguration(); - httpConfiguration.setRequestHeaderSize(2048); - - // HTTP connector - try (ServerConnector httpServerConnector = new ServerConnector(server, - new HttpConnectionFactory(httpConfiguration))) { - httpServerConnector.setPort(nodeConfigManager.getHttpPort()); - httpServerConnector.setIdleTimeout(2000); - - // HTTPS configuration - SslContextFactory sslContextFactory = new SslContextFactory(); - sslContextFactory.setKeyStoreType(nodeConfigManager.getKSType()); - sslContextFactory.setKeyStorePath(nodeConfigManager.getKSFile()); - sslContextFactory.setKeyStorePassword(nodeConfigManager.getKSPass()); - sslContextFactory.setKeyManagerPassword(nodeConfigManager.getKPass()); - - //SP-6: Fixes for SDV scan to exclude/remove DES/3DES - // ciphers are taken care by upgrading jdk in descriptor.xml - sslContextFactory.setExcludeCipherSuites( - "SSL_RSA_WITH_DES_CBC_SHA", - "SSL_DHE_RSA_WITH_DES_CBC_SHA", - "SSL_DHE_DSS_WITH_DES_CBC_SHA", - "SSL_RSA_EXPORT_WITH_RC4_40_MD5", - "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", - "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", - "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" - ); - - sslContextFactory.addExcludeProtocols("SSLv3"); - sslContextFactory.setIncludeProtocols(nodeConfigManager.getEnabledprotocols()); - nodeMainLogger.debug("NODE00004 Unsupported protocols node server:-" - + String.join(",", sslContextFactory.getExcludeProtocols())); - nodeMainLogger.debug("NODE00004 Supported protocols node server:-" - + String.join(",", sslContextFactory.getIncludeProtocols())); - nodeMainLogger.debug("NODE00004 Unsupported ciphers node server:-" - + String.join(",", sslContextFactory.getExcludeCipherSuites())); - - HttpConfiguration httpsConfiguration = new HttpConfiguration(httpConfiguration); - httpsConfiguration.setRequestHeaderSize(8192); - - SecureRequestCustomizer secureRequestCustomizer = new SecureRequestCustomizer(); - secureRequestCustomizer.setStsMaxAge(2000); - secureRequestCustomizer.setStsIncludeSubDomains(true); - httpsConfiguration.addCustomizer(secureRequestCustomizer); - - // HTTPS connector - try (ServerConnector httpsServerConnector = new ServerConnector(server, - new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), - new HttpConnectionFactory(httpsConfiguration))) { - - httpsServerConnector.setPort(nodeConfigManager.getHttpsPort()); - httpsServerConnector.setIdleTimeout(3600000); - httpsServerConnector.setAcceptQueueSize(2); - - //Context Handler - ServletContextHandler servletContextHandler = new ServletContextHandler(0); - servletContextHandler.setContextPath("/"); - servletContextHandler.addServlet(new ServletHolder(new NodeServlet(delivery)), "/*"); - - //CADI Filter activation check - if (nodeConfigManager.getCadiEnabled()) { - servletContextHandler.addFilter(new FilterHolder(new DRNodeCadiFilter(true, - nodeConfigManager.getNodeAafPropsUtils().getPropAccess())), "/*", EnumSet.of(DispatcherType.REQUEST)); - } - - server.setHandler(servletContextHandler); - server.setConnectors(new Connector[]{httpServerConnector, httpsServerConnector}); - } - } - - try { - server.start(); - nodeMainLogger.debug("NODE00006 Node Server started-" + server.getState()); - } catch (Exception e) { - nodeMainLogger.error("NODE00006 Jetty failed to start. Reporting will we unavailable: " - + e.getMessage(), e); - } - server.join(); - nodeMainLogger.debug("NODE00007 Node Server joined - " + server.getState()); - } - - private static class WaitForConfig implements Runnable { - - private NodeConfigManager localNodeConfigManager; - - WaitForConfig(NodeConfigManager ncm) { - this.localNodeConfigManager = ncm; - } - - public synchronized void run() { - notifyAll(); - } - - synchronized void waitForConfig() { - localNodeConfigManager.registerConfigTask(this); - while (!localNodeConfigManager.isConfigured()) { - nodeMainLogger.debug("NODE0003 Waiting for Node Configuration"); - try { - wait(); - } catch (Exception exception) { - nodeMainLogger.error("NodeMain: waitForConfig exception. Exception Message:- " - + exception.toString(), exception); - } - } - localNodeConfigManager.deregisterConfigTask(this); - nodeMainLogger.debug("NODE0004 Node Configuration Data Received"); - } - } -} diff --git a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeRunner.java b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeRunner.java new file mode 100644 index 00000000..2b151ade --- /dev/null +++ b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeRunner.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * ============LICENSE_START================================================== + * * org.onap.dmaap + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ + +package org.onap.dmaap.datarouter.node; + +import static java.lang.System.exit; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import org.eclipse.jetty.server.Server; + +/** + * The main starting point for the Data Router node. + */ +public class NodeRunner { + + private static EELFLogger nodeMainLogger = EELFManager.getInstance().getLogger(NodeRunner.class); + private static NodeConfigManager nodeConfigManager; + + private NodeRunner() { + } + + /** + * Start the data router. + * + *

The location of the node configuration file can be set using the org.onap.dmaap.datarouter.node.properties + * system property. By default, it is "/opt/app/datartr/etc/node.properties". + */ + public static void main(String[] args) { + nodeMainLogger.debug("NODE0001 Data Router Node Starting"); + IsFrom.setDNSCache(); + nodeConfigManager = NodeConfigManager.getInstance(); + nodeMainLogger.debug("NODE0002 I am " + nodeConfigManager.getMyName()); + (new WaitForConfig(nodeConfigManager)).waitForConfig(); + new LogManager(nodeConfigManager); + try { + Server server = NodeServer.getServerInstance(); + server.start(); + server.join(); + nodeMainLogger.debug("NODE00006 Node Server started-" + server.getState()); + } catch (Exception e) { + nodeMainLogger.error("NODE00006 Jetty failed to start. Reporting will we be unavailable: " + + e.getMessage(), e); + exit(1); + } + nodeMainLogger.debug("NODE00007 Node Server joined"); + } + + private static class WaitForConfig implements Runnable { + + private NodeConfigManager localNodeConfigManager; + + WaitForConfig(NodeConfigManager ncm) { + this.localNodeConfigManager = ncm; + } + + public synchronized void run() { + notifyAll(); + } + + synchronized void waitForConfig() { + localNodeConfigManager.registerConfigTask(this); + while (!localNodeConfigManager.isConfigured()) { + nodeMainLogger.debug("NODE0003 Waiting for Node Configuration"); + try { + wait(); + } catch (Exception exception) { + nodeMainLogger.error("NodeMain: waitForConfig exception. Exception Message:- " + + exception.toString(), exception); + } + } + localNodeConfigManager.deregisterConfigTask(this); + nodeMainLogger.debug("NODE0004 Node Configuration Data Received"); + } + } +} diff --git a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeServer.java b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeServer.java new file mode 100644 index 00000000..58fe72b4 --- /dev/null +++ b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeServer.java @@ -0,0 +1,147 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.dmaap.datarouter.node; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.util.EnumSet; +import javax.servlet.DispatcherType; +import javax.servlet.ServletException; +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.SecureRequestCustomizer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.servlet.FilterHolder; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.jetbrains.annotations.NotNull; + + +public class NodeServer { + + private static EELFLogger eelfLogger = EELFManager.getInstance().getLogger(NodeServer.class); + + private static Server server; + private static Delivery delivery; + + private NodeServer(){ + } + + static Server getServerInstance() { + if (server == null) { + server = createNodeServer(NodeConfigManager.getInstance()); + } + return server; + } + + private static Server createNodeServer(NodeConfigManager nodeConfigManager) { + server = new Server(); + delivery = new Delivery(nodeConfigManager); + + HttpConfiguration httpConfiguration = new HttpConfiguration(); + httpConfiguration.setRequestHeaderSize(2048); + + // HTTP connector + try (ServerConnector httpServerConnector = new ServerConnector(server, + new HttpConnectionFactory(httpConfiguration))) { + httpServerConnector.setPort(nodeConfigManager.getHttpPort()); + httpServerConnector.setIdleTimeout(2000); + + SslContextFactory sslContextFactory = getSslContextFactory(nodeConfigManager); + + HttpConfiguration httpsConfiguration = new HttpConfiguration(httpConfiguration); + httpsConfiguration.setRequestHeaderSize(8192); + + SecureRequestCustomizer secureRequestCustomizer = new SecureRequestCustomizer(); + secureRequestCustomizer.setStsMaxAge(2000); + secureRequestCustomizer.setStsIncludeSubDomains(true); + httpsConfiguration.addCustomizer(secureRequestCustomizer); + + // HTTPS connector + try (ServerConnector httpsServerConnector = new ServerConnector(server, + new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), + new HttpConnectionFactory(httpsConfiguration))) { + + httpsServerConnector.setPort(nodeConfigManager.getHttpsPort()); + httpsServerConnector.setIdleTimeout(3600000); + httpsServerConnector.setAcceptQueueSize(2); + + //Context Handler + ServletContextHandler servletContextHandler = new ServletContextHandler(0); + servletContextHandler.setContextPath("/"); + servletContextHandler.addServlet(new ServletHolder(new NodeServlet(delivery)), "/*"); + + //CADI Filter activation check + if (nodeConfigManager.getCadiEnabled()) { + try { + servletContextHandler.addFilter(new FilterHolder(new DRNodeCadiFilter(true, + nodeConfigManager.getNodeAafPropsUtils().getPropAccess())), "/*", + EnumSet.of(DispatcherType.REQUEST)); + } catch (ServletException e) { + eelfLogger.error("Failed to add CADI Filter: " + e.getMessage(), e); + } + } + server.setHandler(servletContextHandler); + server.setConnectors(new Connector[]{httpServerConnector, httpsServerConnector}); + } + } + return server; + } + + /** + * Reset the retry timer for a subscription. + */ + static void resetQueue(String subid, String ip) { + delivery.resetQueue(NodeConfigManager.getInstance().getSpoolDir(subid, ip)); + } + + + @NotNull + private static SslContextFactory getSslContextFactory(NodeConfigManager nodeConfigManager) { + SslContextFactory sslContextFactory = new SslContextFactory(); + sslContextFactory.setKeyStoreType(nodeConfigManager.getKSType()); + sslContextFactory.setKeyStorePath(nodeConfigManager.getKSFile()); + sslContextFactory.setKeyStorePassword(nodeConfigManager.getKSPass()); + sslContextFactory.setKeyManagerPassword(nodeConfigManager.getKPass()); + + sslContextFactory.setExcludeCipherSuites( + "SSL_RSA_WITH_DES_CBC_SHA", + "SSL_DHE_RSA_WITH_DES_CBC_SHA", + "SSL_DHE_DSS_WITH_DES_CBC_SHA", + "SSL_RSA_EXPORT_WITH_RC4_40_MD5", + "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" + ); + + sslContextFactory.addExcludeProtocols("SSLv3"); + eelfLogger.info("Unsupported protocols: " + String.join(",", sslContextFactory.getExcludeProtocols())); + eelfLogger.info("Supported protocols: " + String.join(",", sslContextFactory.getIncludeProtocols())); + eelfLogger.info("Unsupported ciphers: " + String.join(",", sslContextFactory.getExcludeCipherSuites())); + eelfLogger.info("Supported ciphers: " + String.join(",", sslContextFactory.getIncludeCipherSuites())); + return sslContextFactory; + } +} diff --git a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeServlet.java b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeServlet.java index 6fd1def0..388b6793 100644 --- a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeServlet.java +++ b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeServlet.java @@ -130,7 +130,7 @@ public class NodeServlet extends HttpServlet { } else if (path.startsWith("/internal/resetSubscription/")) { String subid = path.substring(28); if (subid.length() != 0 && subid.indexOf('/') == -1) { - NodeMain.resetQueue(subid, ip); + NodeServer.resetQueue(subid, ip); resp.setStatus(HttpServletResponse.SC_NO_CONTENT); return; } diff --git a/datarouter-node/src/main/resources/docker/startup.sh b/datarouter-node/src/main/resources/docker/startup.sh index 8843b221..a71dbaa8 100644 --- a/datarouter-node/src/main/resources/docker/startup.sh +++ b/datarouter-node/src/main/resources/docker/startup.sh @@ -12,7 +12,7 @@ CLASSPATH=$ETC for FILE in `find $LIB -name *.jar`; do CLASSPATH=$CLASSPATH:$FILE done -java -classpath $CLASSPATH org.onap.dmaap.datarouter.node.NodeMain +java -classpath $CLASSPATH org.onap.dmaap.datarouter.node.NodeRunner runner_file="$LIB/datarouter-node-jar-with-dependencies.jar" echo "Starting using" $runner_file diff --git a/datarouter-node/src/main/resources/misc/drtrnode b/datarouter-node/src/main/resources/misc/drtrnode index 970d7d3f..b0e915e5 100644 --- a/datarouter-node/src/main/resources/misc/drtrnode +++ b/datarouter-node/src/main/resources/misc/drtrnode @@ -63,7 +63,7 @@ start() { chmod 755 /opt/app/datartr/spool/s rm -f /opt/app/datartr/etc/SHUTDOWN - nohup java org.onap.dmaap.datarouter.node.NodeMain /dev/null 2>&1 & + nohup java org.onap.dmaap.datarouter.node.NodeRunner /dev/null 2>&1 & sleep 5 PIDS=`pids` if [ "$PIDS" = "" ] diff --git a/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/DeliveryTaskTest.java b/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/DeliveryTaskTest.java index 0123c315..596d56a7 100644 --- a/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/DeliveryTaskTest.java +++ b/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/DeliveryTaskTest.java @@ -23,6 +23,9 @@ package org.onap.dmaap.datarouter.node; import java.io.ByteArrayOutputStream; import java.net.HttpURLConnection; import java.net.URL; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -42,6 +45,8 @@ public class DeliveryTaskTest { @Mock private DeliveryQueue deliveryQueue; + private ExecutorService executorService; + @Before public void setUp() throws Exception { DestInfo destInfo = getPrivDestInfo(); @@ -86,15 +91,23 @@ public class DeliveryTaskTest { } @Test - public void Validate_Delivery_Tasks_Success_For_Standard_File() { + public void Validate_Delivery_Tasks_Success_For_Standard_File() throws InterruptedException { DeliveryTask task = new DeliveryTask(deliveryQueue, "123456789.test-dr-node"); - task.run(); + executorService = Executors.newSingleThreadExecutor(); + executorService.execute(task); + + executorService.shutdown(); + executorService.awaitTermination(2, TimeUnit.SECONDS); } @Test - public void Validate_Delivery_Tasks_Success_For_Compressed_File() { + public void Validate_Delivery_Tasks_Success_For_Compressed_File() throws InterruptedException { DeliveryTask task = new DeliveryTask(deliveryQueue, "123456789.test-dr-node.gz"); - task.run(); + executorService = Executors.newSingleThreadExecutor(); + executorService.execute(task); + + executorService.shutdown(); + executorService.awaitTermination(2, TimeUnit.SECONDS); } private DestInfo getPrivDestInfo() { diff --git a/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/LogbackFilterTest.java b/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/LogbackFilterTest.java index c18528ea..fe9b43c2 100644 --- a/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/LogbackFilterTest.java +++ b/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/LogbackFilterTest.java @@ -309,10 +309,9 @@ public class LogbackFilterTest { } - @Test public void Given_call_to_EelfMsgs_return_the_correct_enum(){ - assertEquals(MESSAGE_WITH_BEHALF.toString(), "MESSAGE_WITH_BEHALF"); + assertEquals("MESSAGE_WITH_BEHALF", MESSAGE_WITH_BEHALF.toString()); } } diff --git a/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeAafPropsUtilsTest.java b/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeAafPropsUtilsTest.java index aa5368b5..927b8bef 100644 --- a/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeAafPropsUtilsTest.java +++ b/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeAafPropsUtilsTest.java @@ -22,18 +22,20 @@ package org.onap.dmaap.datarouter.node; import java.io.File; import java.io.IOException; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; public class NodeAafPropsUtilsTest { + private NodeAafPropsUtils nodeAafPropsUtils; + + @Before + public void setUp() throws IOException { + nodeAafPropsUtils = new NodeAafPropsUtils(new File("src/test/resources/aaf/org.onap.dmaap-dr.props")); + } + @Test public void Veirfy_Aaf_Pass_Decryp_Successful() { - NodeAafPropsUtils nodeAafPropsUtils = null; - try { - nodeAafPropsUtils = new NodeAafPropsUtils(new File("src/test/resources/aaf/org.onap.dmaap-dr.props")); - } catch (IOException e) { - e.printStackTrace(); - } Assert.assertEquals("tVac2#@Stx%tIOE^x[c&2fgZ", nodeAafPropsUtils.getDecryptedPass("cadi_keystore_password")); } } diff --git a/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeConfigManagerTest.java b/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeConfigManagerTest.java index 578053aa..9c945725 100644 --- a/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeConfigManagerTest.java +++ b/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeConfigManagerTest.java @@ -20,30 +20,69 @@ package org.onap.dmaap.datarouter.node; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.io.InputStream; import java.net.InetAddress; import java.net.URL; +import java.net.URLStreamHandler; +import java.net.URLStreamHandlerFactory; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; import org.apache.commons.io.FileUtils; +import org.junit.After; import org.junit.AfterClass; import org.junit.Assert; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.junit.runner.RunWith; +import org.mockito.Mock; import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; +import sun.net.www.URLConnection; -@RunWith(PowerMockRunner.class) @PowerMockIgnore({"javax.net.ssl.*", "javax.security.auth.x500.X500Principal", "javax.crypto.*"}) -@PrepareForTest({InetAddress.class, URL.class}) +@PrepareForTest({InetAddress.class}) public class NodeConfigManagerTest { - private NodeConfigManager nodeConfigManager = NodeConfigManager.getInstance(); + private static HttpUrlStreamHandler httpUrlStreamHandler; + + @Mock + InputStream inputStream; + + @Mock + NodeConfig nodeConfig; @BeforeClass public static void init() { System.setProperty("org.onap.dmaap.datarouter.node.properties", "src/test/resources/node_test.properties"); + // Allows for mocking URL connections + URLStreamHandlerFactory urlStreamHandlerFactory = mock(URLStreamHandlerFactory.class); + URL.setURLStreamHandlerFactory(urlStreamHandlerFactory); + httpUrlStreamHandler = new HttpUrlStreamHandler(); + given(urlStreamHandlerFactory.createURLStreamHandler("https")).willReturn(httpUrlStreamHandler); + } + + @Before + public void reset() throws IOException { + String href = "https://dmaap-dr-prov:8443/internal/prov"; + URLConnection urlConnection = mock(URLConnection.class); + httpUrlStreamHandler.addConnection(new URL(href), urlConnection); + //File prov = new File("src/test/resources/prov_data.json"); + InputStream anyInputStream = new ByteArrayInputStream(Files.readAllBytes(Paths.get("src/test/resources/prov_data.json"))); + when(urlConnection.getInputStream()).thenReturn(anyInputStream); + } + + @After + public void resetHandler() { + httpUrlStreamHandler.resetConnections(); } @AfterClass @@ -54,6 +93,7 @@ public class NodeConfigManagerTest { @Test public void Verify_NodeConfigMan_Getters() { + NodeConfigManager nodeConfigManager = NodeConfigManager.getInstance(); Assert.assertEquals("legacy", nodeConfigManager.getAafInstance()); Assert.assertEquals("src/test/resources/spool/f", nodeConfigManager.getSpoolDir()); Assert.assertEquals("src/test/resources/spool", nodeConfigManager.getSpoolBase()); @@ -70,10 +110,55 @@ public class NodeConfigManagerTest { Assert.assertEquals(new String[] {"TLSv1.1", "TLSv1.2"}, nodeConfigManager.getEnabledprotocols()); Assert.assertEquals("org.onap.dmaap-dr.feed", nodeConfigManager.getAafType()); Assert.assertEquals("publish", nodeConfigManager.getAafAction()); - Assert.assertEquals("https://aaf-locate:8095", nodeConfigManager.getAafURL()); Assert.assertFalse(nodeConfigManager.getCadiEnabled()); Assert.assertFalse(nodeConfigManager.isShutdown()); - Assert.assertFalse(nodeConfigManager.isConfigured()); + Assert.assertTrue(nodeConfigManager.isConfigured()); + Assert.assertEquals("legacy", nodeConfigManager.getAafInstance("1")); + Assert.assertNotNull(nodeConfigManager.getPublishId()); + Assert.assertNotNull(nodeConfigManager.getAllDests()); + Assert.assertEquals(10000, nodeConfigManager.getInitFailureTimer()); + Assert.assertEquals(600000, nodeConfigManager.getWaitForFileProcessFailureTimer()); + Assert.assertEquals(3600000, nodeConfigManager.getMaxFailureTimer()); + Assert.assertEquals(2.0, nodeConfigManager.getFailureBackoff(),0.0); + Assert.assertEquals(86400000, nodeConfigManager.getExpirationTimer()); + Assert.assertEquals(100, nodeConfigManager.getFairFileLimit()); + Assert.assertEquals(60000, nodeConfigManager.getFairTimeLimit()); + Assert.assertNotNull(nodeConfigManager.getTargets("1")); + Assert.assertEquals("src/test/resources/spool/f", nodeConfigManager.getSpoolDir()); + Assert.assertEquals("src/test/resources/aaf/org.onap.dmaap-dr.p12", nodeConfigManager.getKSFile()); + Assert.assertEquals("jks", nodeConfigManager.getTstype()); + Assert.assertEquals("src/test/resources/aaf/org.onap.dmaap-dr.trust.jks", nodeConfigManager.getTsfile()); + Assert.assertEquals(40, nodeConfigManager.getDeliveryThreads()); + Assert.assertEquals("30", nodeConfigManager.getEventLogInterval()); + Assert.assertFalse(nodeConfigManager.isFollowRedirects()); + Assert.assertNotNull(nodeConfigManager.getTimer()); + Assert.assertEquals("1", nodeConfigManager.getFeedId("1")); + Assert.assertEquals("Basic ZG1hYXAtZHItbm9kZTpsaEFUNHY2N3F3blY3QVFxV3ByMm84WXNuVjg9", nodeConfigManager.getMyAuth()); + Assert.assertEquals(0.05, nodeConfigManager.getFreeDiskStart(), 0.0); + Assert.assertEquals(0.2, nodeConfigManager.getFreeDiskStop(), 0.0); + Assert.assertEquals("org.onap.dmaap-dr.feed|legacy|publish", nodeConfigManager.getPermission("legacy")); } + /** + * {@link URLStreamHandler} that allows us to control the {@link URLConnection URLConnections} that are returned + * by {@link URL URLs} in the code under test. + */ + public static class HttpUrlStreamHandler extends URLStreamHandler { + + private Map connections = new HashMap(); + + @Override + protected URLConnection openConnection(URL url) { + return connections.get(url); + } + + void resetConnections() { + connections = new HashMap(); + } + + HttpUrlStreamHandler addConnection(URL url, URLConnection urlConnection) { + connections.put(url, urlConnection); + return this; + } + } } \ No newline at end of file diff --git a/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeServerTest.java b/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeServerTest.java new file mode 100644 index 00000000..f72e581d --- /dev/null +++ b/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeServerTest.java @@ -0,0 +1,119 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.dmaap.datarouter.node; + +import static org.mockito.Matchers.anyObject; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.IOException; +import org.apache.commons.lang3.reflect.FieldUtils; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor; +import org.powermock.modules.junit4.PowerMockRunner; + +@RunWith(PowerMockRunner.class) +@SuppressStaticInitializationFor("org.onap.dmaap.datarouter.node.NodeConfigManager") +public class NodeServerTest { + + private NodeConfigManager config = mock(NodeConfigManager.class); + @Before + public void setUp() throws Exception { + setUpConfig(); + setUpNodeMainDelivery(); + createFilesAndDirectories(); + mock(Delivery.class); + } + + @AfterClass + public static void tearDown() { + deleteCreatedDirectories(); + } + + @Test + public void Verify_Node_Server_Is_Configured_Correctly() { + Assert.assertNotNull(NodeServer.getServerInstance()); + } + + private void setUpConfig() throws IllegalAccessException { + PowerMockito.mockStatic(NodeConfigManager.class); + when(config.isShutdown()).thenReturn(false); + when(config.isConfigured()).thenReturn(true); + when(config.getSpoolDir()).thenReturn("spool/f"); + when(config.getSpoolBase()).thenReturn("spool"); + when(config.getLogDir()).thenReturn("log/dir"); + when(config.getPublishId()).thenReturn("User1"); + when(config.isAnotherNode(anyString(), anyString())).thenReturn(true); + when(config.getEventLogInterval()).thenReturn("40"); + when(config.isDeletePermitted("1")).thenReturn(true); + when(config.getAllDests()).thenReturn(new DestInfo[0]); + when(config.getKSType()).thenReturn("PKCS12"); + when(config.getKSFile()).thenReturn("src/test/resources/aaf/org.onap.dmaap-dr.p12"); + when(config.getKSPass()).thenReturn("tVac2#@Stx%tIOE^x[c&2fgZ"); + when(config.getTstype()).thenReturn("jks"); + when(config.getTsfile()).thenReturn("src/test/resources/aaf/org.onap.dmaap-dr.trust.jks"); + when(config.getTspass()).thenReturn("XHX$2Vl?Lk*2CB.i1+ZFAhZd"); + FieldUtils.writeDeclaredStaticField(NodeServlet.class, "config", config, true); + FieldUtils.writeDeclaredStaticField(NodeRunner.class, "nodeConfigManager", config, true); + PowerMockito.when(NodeConfigManager.getInstance()).thenReturn(config); + } + + private void setUpNodeMainDelivery() throws IllegalAccessException{ + Delivery delivery = mock(Delivery.class); + doNothing().when(delivery).resetQueue(anyObject()); + FieldUtils.writeDeclaredStaticField(NodeServer.class, "delivery", delivery, true); + } + + private void createFilesAndDirectories() throws IOException { + File nodeDir = new File("spool/n/172.0.0.1"); + File spoolDir = new File("spool/s/0/1"); + File dataFile = new File("spool/s/0/1/dmaap-dr-node.1234567"); + File metaDataFile = new File("spool/s/0/1/dmaap-dr-node.1234567.M"); + nodeDir.mkdirs(); + spoolDir.mkdirs(); + dataFile.createNewFile(); + metaDataFile.createNewFile(); + } + + private static void deleteCreatedDirectories() { + File spoolDir = new File("spool"); + delete(spoolDir); + } + + private static void delete(File file) { + if (file.isDirectory()) { + for (File f: file.listFiles()) { + delete(f); + } + } + if (!file.delete()) { + System.out.println("Failed to delete: " + file); + } + } + +} diff --git a/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeServletTest.java b/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeServletTest.java index b3db3201..136e21d4 100644 --- a/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeServletTest.java +++ b/datarouter-node/src/test/java/org/onap/dmaap/datarouter/node/NodeServletTest.java @@ -307,7 +307,7 @@ public class NodeServletTest { when(config.isDeletePermitted("1")).thenReturn(true); when(config.getAllDests()).thenReturn(new DestInfo[0]); FieldUtils.writeDeclaredStaticField(NodeServlet.class, "config", config, true); - FieldUtils.writeDeclaredStaticField(NodeMain.class, "nodeConfigManager", config, true); + FieldUtils.writeDeclaredStaticField(NodeRunner.class, "nodeConfigManager", config, true); PowerMockito.when(NodeConfigManager.getInstance()).thenReturn(config); } @@ -318,7 +318,7 @@ public class NodeServletTest { when(config.isConfigured()).thenReturn(true); when(config.isDeletePermitted("1")).thenReturn(false); FieldUtils.writeDeclaredStaticField(NodeServlet.class, "config", config, true); - FieldUtils.writeDeclaredStaticField(NodeMain.class, "nodeConfigManager", config, true); + FieldUtils.writeDeclaredStaticField(NodeRunner.class, "nodeConfigManager", config, true); PowerMockito.when(NodeConfigManager.getInstance()).thenReturn(config); } @@ -329,14 +329,14 @@ public class NodeServletTest { when(config.isConfigured()).thenReturn(true); when(config.isDeletePermitted("1")).thenThrow(new NullPointerException()); FieldUtils.writeDeclaredStaticField(NodeServlet.class, "config", config, true); - FieldUtils.writeDeclaredStaticField(NodeMain.class, "nodeConfigManager", config, true); + FieldUtils.writeDeclaredStaticField(NodeRunner.class, "nodeConfigManager", config, true); PowerMockito.when(NodeConfigManager.getInstance()).thenReturn(config); } private void setUpNodeMainDelivery() throws IllegalAccessException{ Delivery delivery = mock(Delivery.class); doNothing().when(delivery).resetQueue(anyObject()); - FieldUtils.writeDeclaredStaticField(NodeMain.class, "delivery", delivery, true); + FieldUtils.writeDeclaredStaticField(NodeServer.class, "delivery", delivery, true); } private void setNodeConfigManagerIsConfiguredToReturnFalse() throws IllegalAccessException{ diff --git a/datarouter-node/src/test/resources/aaf/org.onap.dmaap-dr.cred.props b/datarouter-node/src/test/resources/aaf/org.onap.dmaap-dr.cred.props index 3f081b5d..70d01908 100644 --- a/datarouter-node/src/test/resources/aaf/org.onap.dmaap-dr.cred.props +++ b/datarouter-node/src/test/resources/aaf/org.onap.dmaap-dr.cred.props @@ -12,6 +12,6 @@ cadi_keystore=src/test/resources/aaf/org.onap.dmaap-dr.p12 cadi_keystore_password=enc:NwhywpJzc4rlcpwkPRs4GWkOliMQDb8d7kmKKK2QwtwQu4Q7i_psLw0baQ-NY3mF cadi_keystore_password_jks=enc:McsNbnuHb5tgoa_UMgdTdHqWEG4bt6VcPsc_NTzS277aDcrNRutDSBDYyyLD5no2 cadi_keystore_password_p12=enc:NwhywpJzc4rlcpwkPRs4GWkOliMQDb8d7kmKKK2QwtwQu4Q7i_psLw0baQ-NY3mF -cadi_truststore=/opt/app/osaaf/local/org.onap.dmaap-dr.trust.jks +cadi_truststore=src/test/resources/aaf/org.onap.dmaap-dr.trust.jks cadi_truststore_password=enc:xWbQBg4WdbHbQgvKGrol0ns16g9jgFYteR3nQkwTl65BtvtWf_ZKhSVP8w_Z0VHU cadi_x509_issuers=CN=intermediateCA_1, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_7, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_9, OU=OSAAF, O=ONAP, C=US diff --git a/datarouter-node/src/test/resources/aaf/org.onap.dmaap-dr.trust.jks b/datarouter-node/src/test/resources/aaf/org.onap.dmaap-dr.trust.jks new file mode 100644 index 0000000000000000000000000000000000000000..c837fa05c612e4d064025aa15ed1ea4858f3a452 GIT binary patch literal 1413 zcmb7DYdF&j9NtyOZA)qvbBlJCL;Yv1rf96lVM3Y-#S&HxsU!Di?6id@x7^BHJA@UB zx#Yf-`H z$M9i=_%T>Mz=jmWA7y2L;2wL4fCUHyrvM!I5r6~57D6Fl2t*l_|8TCoOez)t>PpHc zJbT_}bud^J4gyT^2tZ88Z|Wx zbg;=`H1l)yHQ^9-(RnXel$PCpOb*B!*8+%T$i9hQ$6*KJe~1Rk(*HR{4-5GWc)u49hemwH6y9sje>Zsv=rwmA#V17u$4Ee zj6BRt2rKqo%XpsxYYsHvkCbHQMH7$uEOzy&VJdKETRTu)ZLUeTV%ObqV^e7%OAU`~ zub)V8FKZD;@o#jbuOt1%6R%x{MK=w~o>({cJFM-FxxB#1h_o?c+_K7&Y^!jl9ndkO zu8I2FZ|`2D{JyNl^XTB!N9s@b))C{r7i+jmZSNms)r^!4)89Bl1E@np(oE~po5fO2 z?q_Wm2}?;f2Fc!@H2QI{XRs%mD2koXq<==_$q1FPs&^4|V}^QXrAb9~$m?2%0g^YY z1=Y(ZhoKm173#l2aiPSvwOb4Ub~d zakA9m>%6E#t{oyDAd$Spkr~YXr+e$Lg zPF|@(9TH|DN3GCp_^l6z+8B}UUt*Qt4tNFLJEZ}EfVZW=Vf;B^=rfNlVQ*c6bP0&JroydPt@ z(Ta^2fwv3Xm4!!-=?cTQKMfqNu z8GXAeC1@dnM>U%=*m~ZBtf|N ziC$D9mgZ2^*y4D+Kg1CHp}Wp*C>tRUPy9rDtPQKB-Yd9q5pEI_eR#k;26tu{iC7u? zG!eIBnrr4c4ugxrgBeHK-O^Gmcv)>iWT}ZFj?J}k$Nuu6e>E&sxE&Xq#626daE_xb z=j*TEFDpk8o~q)Oabv-<^wM<}+d^BEMo8A_4R5f-8T?h8dt6gY*f$j*_a$2%E4^24 zNY@-}4Wvvn3&G{9y;CFPy7oO^q>hEJJ+e*~31&}>fpi}fEnf4jpFuM@n8D#g^aX)+ zXzr&|v9if4kIJ09jb(|un(nM3?{*0%$1qv5=0By?Qdq|nF64$gZ79Re>*JSP{Z9vS zt))|B_V;sqy5+Wy=op2gP%7dYolGquN-&Q{qpu;~p?1c+6)e1XbpfLl#-kd_LbuKM SO$W7%Rx9mivGi81I{Xb!S7Jv1 literal 0 HcmV?d00001 diff --git a/datarouter-node/src/test/resources/prov_data.json b/datarouter-node/src/test/resources/prov_data.json new file mode 100644 index 00000000..cf455c71 --- /dev/null +++ b/datarouter-node/src/test/resources/prov_data.json @@ -0,0 +1,129 @@ +{ + "feeds": [ + { + "suspend": false, + "groupid": 0, + "description": "Default feed provisioned for PM File collector", + "version": "m1.0", + "authorization": { + "endpoint_addrs": [ + + ], + "classification": "unclassified", + "endpoint_ids": [ + { + "password": "dradmin", + "id": "dradmin" + } + ] + }, + "last_mod": 1560871903000, + "deleted": false, + "feedid": 1, + "name": "Default PM Feed", + "business_description": "Default Feed", + "aaf_instance": "legacy", + "publisher": "dradmin", + "links": { + "subscribe": "https://dmaap-dr-prov/subscribe/1", + "log": "https://dmaap-dr-prov/feedlog/1", + "publish": "https://dmaap-dr-prov/publish/1", + "self": "https://dmaap-dr-prov/feed/1" + }, + "created_date": 1560871903000 + } + ], + "groups": [ + { + "authid": "GROUP-0000-c2754bb7-92ef-4869-9c6b-1bc1283be4c0", + "name": "Test Group", + "description": "Test Description of Group .", + "classification": "publisher/subscriber", + "members": "{id=attuid, name=User1}, {id=attuid, name=User 2]" + } + ], + "subscriptions": [ + { + "suspend": false, + "delivery": { + "use100": true, + "password": "PASSWORD", + "user": "LOGIN", + "url": "https://dcae-pm-mapper:8443/delivery" + }, + "subscriber": "dradmin", + "groupid": 0, + "metadataOnly": false, + "privilegedSubscriber": true, + "subid": 1, + "last_mod": 1560872889000, + "feedid": 1, + "follow_redirect": false, + "decompress": true, + "aaf_instance": "legacy", + "links": { + "feed": "https://dmaap-dr-prov/feed/1", + "log": "https://dmaap-dr-prov/sublog/1", + "self": "https://dmaap-dr-prov/subs/1" + }, + "created_date": 1560872889000 + } + ], + "parameters": { + "ACTIVE_POD": "dmaap-dr-prov", + "DELIVERY_FILE_PROCESS_INTERVAL": 600, + "DELIVERY_INIT_RETRY_INTERVAL": 10, + "DELIVERY_MAX_AGE": 86400, + "DELIVERY_MAX_RETRY_INTERVAL": 3600, + "DELIVERY_RETRY_RATIO": 2, + "LOGROLL_INTERVAL": 30, + "NODES": [ + "dmaap-dr-node" + ], + "PROV_ACTIVE_NAME": "dmaap-dr-prov", + "PROV_AUTH_ADDRESSES": [ + "dmaap-dr-prov", + "dmaap-dr-node" + ], + "PROV_AUTH_SUBJECTS": [ + "" + ], + "PROV_DOMAIN": "", + "PROV_MAXFEED_COUNT": 10000, + "PROV_MAXSUB_COUNT": 100000, + "PROV_NAME": "dmaap-dr-prov", + "PROV_REQUIRE_CERT": "false", + "PROV_REQUIRE_SECURE": "true", + "STANDBY_POD": "", + "_INT_VALUES": [ + "LOGROLL_INTERVAL", + "PROV_MAXFEED_COUNT", + "PROV_MAXSUB_COUNT", + "DELIVERY_INIT_RETRY_INTERVAL", + "DELIVERY_MAX_RETRY_INTERVAL", + "DELIVERY_RETRY_RATIO", + "DELIVERY_MAX_AGE", + "DELIVERY_FILE_PROCESS_INTERVAL" + ] + }, + "ingress": [ + { + "feedid": 1, + "subnet": "", + "user": "", + "node": [ + "stub_from." + ] + } + ], + "egress": { + "1": "stub_to." + }, + "routing": [ + { + "from": 1, + "to": 3, + "via": 2 + } + ] +} \ No newline at end of file diff --git a/datarouter-prov/pom.xml b/datarouter-prov/pom.xml index 20ce7ce3..791cbc3e 100755 --- a/datarouter-prov/pom.xml +++ b/datarouter-prov/pom.xml @@ -407,7 +407,7 @@ **/src/main/java/org/onap/dmaap/datarouter/reports/** src/main/java/org/onap/dmaap/datarouter/authz/impl/AuthRespSupplementImpl.java - src/main/java/org/onap/dmaap/datarouter/provisioning/Main.java + src/main/java/org/onap/dmaap/datarouter/provisioning/ProvRunner.java src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DRRouteCLI.java diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/ProvRunner.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/ProvRunner.java index 4078922e..8a0ef448 100644 --- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/ProvRunner.java +++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/ProvRunner.java @@ -32,37 +32,15 @@ import com.att.eelf.configuration.EELFManager; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.security.Security; -import java.util.EnumSet; import java.util.Properties; import java.util.Timer; -import javax.servlet.DispatcherType; -import org.eclipse.jetty.http.HttpVersion; -import org.eclipse.jetty.server.Connector; -import org.eclipse.jetty.server.Handler; -import org.eclipse.jetty.server.HttpConfiguration; -import org.eclipse.jetty.server.HttpConnectionFactory; -import org.eclipse.jetty.server.NCSARequestLog; import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.eclipse.jetty.server.SslConnectionFactory; -import org.eclipse.jetty.server.handler.ContextHandlerCollection; -import org.eclipse.jetty.server.handler.DefaultHandler; -import org.eclipse.jetty.server.handler.HandlerCollection; -import org.eclipse.jetty.server.handler.RequestLogHandler; -import org.eclipse.jetty.servlet.FilterHolder; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.util.ssl.SslContextFactory; -import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.onap.dmaap.datarouter.provisioning.utils.AafPropsUtils; -import org.onap.dmaap.datarouter.provisioning.utils.DRProvCadiFilter; import org.onap.dmaap.datarouter.provisioning.utils.LogfileLoader; import org.onap.dmaap.datarouter.provisioning.utils.Poker; import org.onap.dmaap.datarouter.provisioning.utils.ProvDbUtils; import org.onap.dmaap.datarouter.provisioning.utils.PurgeLogDirTask; import org.onap.dmaap.datarouter.provisioning.utils.SynchronizerTask; -import org.onap.dmaap.datarouter.provisioning.utils.ThrottleFilter; /** *

@@ -98,10 +76,7 @@ public class ProvRunner { public static final EELFLogger intlogger = EELFManager.getInstance() .getLogger("org.onap.dmaap.datarouter.provisioning.internal"); - /** - * The one and only {@link Server} instance in this JVM. - */ - private static Server server; + private static Server provServer; private static AafPropsUtils aafPropsUtils; private static Properties provProperties; @@ -109,199 +84,50 @@ public class ProvRunner { * Starts the Data Router Provisioning server. * * @param args not used - * @throws Exception if Jetty has a problem starting */ - public static void main(String[] args) throws Exception { - - intlogger.info("PROV0000 **** Data Router Provisioning Server starting...."); - + public static void main(String[] args) { // Check DB is accessible and contains the expected tables if (!ProvDbUtils.getInstance().initProvDB()) { intlogger.error("Data Router Provisioning database init failure. Exiting."); exit(1); } - - int httpPort = Integer.parseInt( - getProvProperties().getProperty("org.onap.dmaap.datarouter.provserver.http.port", "8080")); - final int httpsPort = Integer.parseInt( - getProvProperties().getProperty("org.onap.dmaap.datarouter.provserver.https.port", "8443")); - - Security.setProperty("networkaddress.cache.ttl", "4"); - // Server's thread pool - QueuedThreadPool queuedThreadPool = new QueuedThreadPool(); - queuedThreadPool.setMinThreads(10); - queuedThreadPool.setMaxThreads(200); - queuedThreadPool.setDetailedDump(false); - - // The server itself - server = new Server(queuedThreadPool); - server.setStopAtShutdown(true); - server.setStopTimeout(5000); - server.setDumpAfterStart(false); - server.setDumpBeforeStop(false); - - // Request log configuration - NCSARequestLog ncsaRequestLog = new NCSARequestLog(); - ncsaRequestLog.setFilename(getProvProperties() - .getProperty("org.onap.dmaap.datarouter.provserver.accesslog.dir") - + "/request.log.yyyy_mm_dd"); - ncsaRequestLog.setFilenameDateFormat("yyyyMMdd"); - ncsaRequestLog.setRetainDays(90); - ncsaRequestLog.setAppend(true); - ncsaRequestLog.setExtended(false); - ncsaRequestLog.setLogCookies(false); - ncsaRequestLog.setLogTimeZone("GMT"); - - RequestLogHandler requestLogHandler = new RequestLogHandler(); - requestLogHandler.setRequestLog(ncsaRequestLog); - server.setRequestLog(ncsaRequestLog); - - // HTTP configuration - HttpConfiguration httpConfiguration = new HttpConfiguration(); - httpConfiguration.setSecureScheme("https"); - httpConfiguration.setSecurePort(httpsPort); - httpConfiguration.setOutputBufferSize(32768); - httpConfiguration.setRequestHeaderSize(8192); - httpConfiguration.setResponseHeaderSize(8192); - httpConfiguration.setSendServerVersion(true); - httpConfiguration.setSendDateHeader(false); - + // Set up AAF properties try { - AafPropsUtils.init(new File(getProvProperties().getProperty( + aafPropsUtils = new AafPropsUtils(new File(getProvProperties().getProperty( "org.onap.dmaap.datarouter.provserver.aafprops.path", "/opt/app/osaaf/local/org.onap.dmaap-dr.props"))); } catch (IOException e) { intlogger.error("NODE0314 Failed to load AAF props. Exiting", e); exit(1); } - aafPropsUtils = AafPropsUtils.getInstance(); - - //HTTP Connector - HandlerCollection handlerCollection; - try (ServerConnector httpServerConnector = - new ServerConnector(server, new HttpConnectionFactory(httpConfiguration))) { - httpServerConnector.setPort(httpPort); - httpServerConnector.setAcceptQueueSize(2); - httpServerConnector.setIdleTimeout(300000); - - // SSL Context - SslContextFactory sslContextFactory = new SslContextFactory(); - sslContextFactory.setKeyStoreType(AafPropsUtils.KEYSTORE_TYPE_PROPERTY); - sslContextFactory.setKeyStorePath(getAafPropsUtils().getKeystorePathProperty()); - sslContextFactory.setKeyStorePassword(getAafPropsUtils().getKeystorePassProperty()); - sslContextFactory.setKeyManagerPassword(getAafPropsUtils().getKeystorePassProperty()); - - String truststorePathProperty = getAafPropsUtils().getTruststorePathProperty(); - if (truststorePathProperty != null && truststorePathProperty.length() > 0) { - intlogger.info("@@ TS -> " + truststorePathProperty); - sslContextFactory.setTrustStoreType(AafPropsUtils.TRUESTSTORE_TYPE_PROPERTY); - sslContextFactory.setTrustStorePath(truststorePathProperty); - sslContextFactory.setTrustStorePassword(getAafPropsUtils().getTruststorePassProperty()); - } else { - sslContextFactory.setTrustStorePath(AafPropsUtils.DEFAULT_TRUSTSTORE); - sslContextFactory.setTrustStorePassword("changeit"); - } - - sslContextFactory.setWantClientAuth(true); - sslContextFactory.setExcludeCipherSuites( - "SSL_RSA_WITH_DES_CBC_SHA", - "SSL_DHE_RSA_WITH_DES_CBC_SHA", - "SSL_DHE_DSS_WITH_DES_CBC_SHA", - "SSL_RSA_EXPORT_WITH_RC4_40_MD5", - "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", - "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", - "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" - ); - sslContextFactory.addExcludeProtocols("SSLv3"); - sslContextFactory.setIncludeProtocols(getProvProperties().getProperty( - "org.onap.dmaap.datarouter.provserver.https.include.protocols", - "TLSv1.1|TLSv1.2").trim().split("\\|")); - - intlogger.info("Not supported protocols prov server:-" - + String.join(",", sslContextFactory.getExcludeProtocols())); - intlogger.info("Supported protocols prov server:-" - + String.join(",", sslContextFactory.getIncludeProtocols())); - intlogger.info("Not supported ciphers prov server:-" - + String.join(",", sslContextFactory.getExcludeCipherSuites())); - intlogger.info("Supported ciphers prov server:-" - + String.join(",", sslContextFactory.getIncludeCipherSuites())); - - // HTTPS configuration - HttpConfiguration httpsConfiguration = new HttpConfiguration(httpConfiguration); - httpsConfiguration.setRequestHeaderSize(8192); - - // HTTPS connector - try (ServerConnector httpsServerConnector = new ServerConnector(server, - new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), - new HttpConnectionFactory(httpsConfiguration))) { - - httpsServerConnector.setPort(httpsPort); - httpsServerConnector.setIdleTimeout(30000); - httpsServerConnector.setAcceptQueueSize(2); - - // Servlet and Filter configuration - ServletContextHandler servletContextHandler = new ServletContextHandler(0); - servletContextHandler.setContextPath("/"); - servletContextHandler.addServlet(new ServletHolder(new FeedServlet()), "/feed/*"); - servletContextHandler.addServlet(new ServletHolder(new FeedLogServlet()), "/feedlog/*"); - servletContextHandler.addServlet(new ServletHolder(new PublishServlet()), "/publish/*"); - servletContextHandler.addServlet(new ServletHolder(new SubscribeServlet()), "/subscribe/*"); - servletContextHandler.addServlet(new ServletHolder(new StatisticsServlet()), "/statistics/*"); - servletContextHandler.addServlet(new ServletHolder(new SubLogServlet()), "/sublog/*"); - servletContextHandler.addServlet(new ServletHolder(new GroupServlet()), "/group/*"); - servletContextHandler.addServlet(new ServletHolder(new SubscriptionServlet()), "/subs/*"); - servletContextHandler.addServlet(new ServletHolder(new InternalServlet()), "/internal/*"); - servletContextHandler.addServlet(new ServletHolder(new RouteServlet()), "/internal/route/*"); - servletContextHandler.addServlet(new ServletHolder(new DRFeedsServlet()), "/"); - servletContextHandler.addFilter(new FilterHolder(new ThrottleFilter()), - "/publish/*", EnumSet.of(DispatcherType.REQUEST)); - - //CADI Filter activation check - if (Boolean.parseBoolean(getProvProperties().getProperty( - "org.onap.dmaap.datarouter.provserver.cadi.enabled", "false"))) { - servletContextHandler.addFilter(new FilterHolder(new DRProvCadiFilter(true, getAafPropsUtils().getPropAccess())), - "/*", EnumSet.of(DispatcherType.REQUEST)); - intlogger.info("PROV0001 AAF CADI Auth enabled for "); - } - - ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection(); - contextHandlerCollection.addHandler(servletContextHandler); - - // Server's Handler collection - handlerCollection = new HandlerCollection(); - handlerCollection.setHandlers(new Handler[]{contextHandlerCollection, new DefaultHandler()}); - handlerCollection.addHandler(requestLogHandler); - - server.setConnectors(new Connector[]{httpServerConnector, httpsServerConnector}); - } - } - server.setHandler(handlerCollection); - // Daemon to clean up the log directory on a daily basis Timer rolex = new Timer(); rolex.scheduleAtFixedRate(new PurgeLogDirTask(), 0, 86400000L); // run once per day - // Start LogfileLoader - LogfileLoader.getLoader(); - try { - server.start(); - intlogger.info("Prov Server started-" + server.getState()); + // Create and start the Jetty server + provServer = ProvServer.getServerInstance(); + intlogger.info("PROV0000 **** DMaaP Data Router Provisioning Server starting...."); + provServer.start(); + provServer.dumpStdErr(); + provServer.join(); + intlogger.info("PROV0000 **** DMaaP Data Router Provisioning Server started: " + provServer.getState()); } catch (Exception e) { - intlogger.error("Jetty failed to start. Exiting: " + e.getMessage(), e); + intlogger.error( + "PROV0010 **** DMaaP Data Router Provisioning Server failed to start. Exiting: " + e.getMessage(), e); exit(1); } - server.join(); - intlogger.info("PROV0001 **** AT&T Data Router Provisioning Server halted."); + // Start LogfileLoader + LogfileLoader.getLoader(); } /** * Stop the Jetty server. */ - public static void shutdown() { + static void shutdown() { new Thread(() -> { try { - server.stop(); + provServer.stop(); Thread.sleep(5000L); exit(0); } catch (Exception e) { diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/ProvServer.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/ProvServer.java new file mode 100644 index 00000000..c0e6b8d6 --- /dev/null +++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/ProvServer.java @@ -0,0 +1,236 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.dmaap.datarouter.provisioning; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.security.Security; +import java.util.EnumSet; +import java.util.Properties; +import javax.servlet.DispatcherType; +import javax.servlet.ServletException; +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.NCSARequestLog; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.server.handler.ContextHandlerCollection; +import org.eclipse.jetty.server.handler.DefaultHandler; +import org.eclipse.jetty.server.handler.HandlerCollection; +import org.eclipse.jetty.server.handler.RequestLogHandler; +import org.eclipse.jetty.servlet.FilterHolder; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.jetbrains.annotations.NotNull; +import org.onap.dmaap.datarouter.provisioning.utils.AafPropsUtils; +import org.onap.dmaap.datarouter.provisioning.utils.DRProvCadiFilter; +import org.onap.dmaap.datarouter.provisioning.utils.ThrottleFilter; + + +public class ProvServer { + + public static final EELFLogger intlogger = EELFManager.getInstance() + .getLogger("InternalLog"); + + private static Server server; + + private ProvServer() { + } + + static Server getServerInstance() { + if (server == null) { + server = createProvServer(ProvRunner.getProvProperties()); + } + return server; + } + + private static Server createProvServer(Properties provProps) { + final int httpsPort = Integer.parseInt( + provProps.getProperty("org.onap.dmaap.datarouter.provserver.https.port", "8443")); + + Security.setProperty("networkaddress.cache.ttl", "4"); + QueuedThreadPool queuedThreadPool = getQueuedThreadPool(); + + server = new Server(queuedThreadPool); + server.setStopAtShutdown(true); + server.setStopTimeout(5000); + server.setDumpAfterStart(false); + server.setDumpBeforeStop(false); + + NCSARequestLog ncsaRequestLog = getRequestLog(provProps); + RequestLogHandler requestLogHandler = new RequestLogHandler(); + requestLogHandler.setRequestLog(ncsaRequestLog); + + server.setRequestLog(ncsaRequestLog); + + HttpConfiguration httpConfiguration = getHttpConfiguration(httpsPort); + + //HTTP Connector + try (ServerConnector httpServerConnector = new ServerConnector(server, + new HttpConnectionFactory(httpConfiguration))) { + httpServerConnector.setPort(Integer.parseInt(provProps.getProperty( + "org.onap.dmaap.datarouter.provserver.http.port", "8080"))); + httpServerConnector.setAcceptQueueSize(2); + httpServerConnector.setIdleTimeout(30000); + + SslContextFactory sslContextFactory = getSslContextFactory(provProps); + + // HTTPS configuration + HttpConfiguration httpsConfiguration = new HttpConfiguration(httpConfiguration); + httpsConfiguration.setRequestHeaderSize(8192); + + // HTTPS connector + try (ServerConnector httpsServerConnector = new ServerConnector(server, + new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), + new HttpConnectionFactory(httpsConfiguration))) { + httpsServerConnector.setPort(httpsPort); + httpsServerConnector.setIdleTimeout(30000); + httpsServerConnector.setAcceptQueueSize(2); + + ServletContextHandler servletContextHandler = getServletContextHandler(provProps); + ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection(); + contextHandlerCollection.addHandler(servletContextHandler); + + // Server's Handler collection + HandlerCollection handlerCollection = new HandlerCollection(); + handlerCollection.setHandlers(new Handler[]{contextHandlerCollection, new DefaultHandler()}); + handlerCollection.addHandler(requestLogHandler); + + server.setConnectors(new Connector[]{httpServerConnector, httpsServerConnector}); + server.setHandler(handlerCollection); + } + } + return server; + } + + @NotNull + private static QueuedThreadPool getQueuedThreadPool() { + // Server's thread pool + QueuedThreadPool queuedThreadPool = new QueuedThreadPool(); + queuedThreadPool.setMinThreads(10); + queuedThreadPool.setMaxThreads(200); + queuedThreadPool.setDetailedDump(false); + return queuedThreadPool; + } + + @NotNull + private static SslContextFactory getSslContextFactory(Properties provProps) { + SslContextFactory sslContextFactory = new SslContextFactory(); + sslContextFactory.setKeyStoreType(AafPropsUtils.KEYSTORE_TYPE_PROPERTY); + sslContextFactory.setKeyStorePath(ProvRunner.getAafPropsUtils().getKeystorePathProperty()); + sslContextFactory.setKeyStorePassword(ProvRunner.getAafPropsUtils().getKeystorePassProperty()); + sslContextFactory.setKeyManagerPassword(ProvRunner.getAafPropsUtils().getKeystorePassProperty()); + + sslContextFactory.setTrustStoreType(AafPropsUtils.TRUESTSTORE_TYPE_PROPERTY); + sslContextFactory.setTrustStorePath(ProvRunner.getAafPropsUtils().getTruststorePathProperty()); + sslContextFactory.setTrustStorePassword(ProvRunner.getAafPropsUtils().getTruststorePassProperty()); + + sslContextFactory.setWantClientAuth(true); + sslContextFactory.setExcludeCipherSuites( + "SSL_RSA_WITH_DES_CBC_SHA", + "SSL_DHE_RSA_WITH_DES_CBC_SHA", + "SSL_DHE_DSS_WITH_DES_CBC_SHA", + "SSL_RSA_EXPORT_WITH_RC4_40_MD5", + "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" + ); + sslContextFactory.addExcludeProtocols("SSLv3"); + sslContextFactory.setIncludeProtocols(provProps.getProperty( + "org.onap.dmaap.datarouter.provserver.https.include.protocols", + "TLSv1.1|TLSv1.2").trim().split("\\|")); + + intlogger.info("Unsupported protocols: " + String.join(",", sslContextFactory.getExcludeProtocols())); + intlogger.info("Supported protocols: " + String.join(",", sslContextFactory.getIncludeProtocols())); + intlogger.info("Unsupported ciphers: " + String.join(",", sslContextFactory.getExcludeCipherSuites())); + intlogger.info("Supported ciphers: " + String.join(",", sslContextFactory.getIncludeCipherSuites())); + + return sslContextFactory; + } + + @NotNull + private static NCSARequestLog getRequestLog(Properties provProps) { + NCSARequestLog ncsaRequestLog = new NCSARequestLog(); + ncsaRequestLog.setFilename(provProps.getProperty( + "org.onap.dmaap.datarouter.provserver.accesslog.dir") + "/request.log.yyyy_mm_dd"); + ncsaRequestLog.setFilenameDateFormat("yyyyMMdd"); + ncsaRequestLog.setRetainDays(90); + ncsaRequestLog.setAppend(true); + ncsaRequestLog.setExtended(false); + ncsaRequestLog.setLogCookies(false); + ncsaRequestLog.setLogTimeZone("GMT"); + return ncsaRequestLog; + } + + @NotNull + private static HttpConfiguration getHttpConfiguration(int httpsPort) { + HttpConfiguration httpConfiguration = new HttpConfiguration(); + httpConfiguration.setSecureScheme("https"); + httpConfiguration.setSecurePort(httpsPort); + httpConfiguration.setOutputBufferSize(32768); + httpConfiguration.setRequestHeaderSize(8192); + httpConfiguration.setResponseHeaderSize(8192); + httpConfiguration.setSendServerVersion(true); + httpConfiguration.setSendDateHeader(false); + return httpConfiguration; + } + + @NotNull + private static ServletContextHandler getServletContextHandler(Properties provProps) { + ServletContextHandler servletContextHandler = new ServletContextHandler(0); + servletContextHandler.setContextPath("/"); + servletContextHandler.addServlet(new ServletHolder(new FeedServlet()), "/feed/*"); + servletContextHandler.addServlet(new ServletHolder(new FeedLogServlet()), "/feedlog/*"); + servletContextHandler.addServlet(new ServletHolder(new PublishServlet()), "/publish/*"); + servletContextHandler.addServlet(new ServletHolder(new SubscribeServlet()), "/subscribe/*"); + servletContextHandler.addServlet(new ServletHolder(new StatisticsServlet()), "/statistics/*"); + servletContextHandler.addServlet(new ServletHolder(new SubLogServlet()), "/sublog/*"); + servletContextHandler.addServlet(new ServletHolder(new GroupServlet()), "/group/*"); + servletContextHandler.addServlet(new ServletHolder(new SubscriptionServlet()), "/subs/*"); + servletContextHandler.addServlet(new ServletHolder(new InternalServlet()), "/internal/*"); + servletContextHandler.addServlet(new ServletHolder(new RouteServlet()), "/internal/route/*"); + servletContextHandler.addServlet(new ServletHolder(new DRFeedsServlet()), "/"); + servletContextHandler.addFilter(new FilterHolder(new ThrottleFilter()), + "/publish/*", EnumSet.of(DispatcherType.REQUEST)); + setCadiFilter(servletContextHandler, provProps); + return servletContextHandler; + } + + private static void setCadiFilter(ServletContextHandler servletContextHandler, Properties provProps) { + if (Boolean.parseBoolean(provProps.getProperty( + "org.onap.dmaap.datarouter.provserver.cadi.enabled", "false"))) { + try { + servletContextHandler.addFilter(new FilterHolder(new DRProvCadiFilter( + true, ProvRunner.getAafPropsUtils().getPropAccess())), "/*", EnumSet.of(DispatcherType.REQUEST)); + intlogger.info("PROV0001 AAF CADI filter enabled"); + } catch (ServletException e) { + intlogger.error("PROV0001 Failed to add CADI filter to server"); + } + + } + } +} diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/ProxyServlet.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/ProxyServlet.java index d84e4925..089ea755 100755 --- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/ProxyServlet.java +++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/ProxyServlet.java @@ -87,10 +87,6 @@ public class ProxyServlet extends BaseServlet { // Set up truststore store = ProvRunner.getAafPropsUtils().getTruststorePathProperty(); pass = ProvRunner.getAafPropsUtils().getTruststorePassProperty(); - if (store == null || store.length() == 0) { - store = AafPropsUtils.DEFAULT_TRUSTSTORE; - pass = "changeit"; - } KeyStore trustStore = readStore(store, pass, AafPropsUtils.TRUESTSTORE_TYPE_PROPERTY); // We are connecting with the node name, but the certificate will have the CNAME diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/EgressRoute.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/EgressRoute.java index 8cd19866..bd18280e 100644 --- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/EgressRoute.java +++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/EgressRoute.java @@ -100,10 +100,11 @@ public class EgressRoute extends NodeClass implements Comparable { try (Connection conn = ProvDbUtils.getInstance().getConnection(); PreparedStatement ps = conn.prepareStatement("select NODEID from EGRESS_ROUTES where SUBID = ?")) { ps.setInt(1, sub); - ResultSet rs = ps.executeQuery(); - if (rs.next()) { - int node = rs.getInt("NODEID"); - er = new EgressRoute(sub, node); + try (ResultSet rs = ps.executeQuery()) { + if (rs.next()) { + int node = rs.getInt("NODEID"); + er = new EgressRoute(sub, node); + } } } catch (SQLException e) { intlogger.error("PROV0009 EgressRoute.getEgressRoute: " + e.getMessage(), e); diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/Parameters.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/Parameters.java index 14a0a9dc..79fc91b1 100644 --- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/Parameters.java +++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/beans/Parameters.java @@ -108,8 +108,8 @@ public class Parameters extends Syncable { public static Collection getParameterCollection() { Collection coll = new ArrayList<>(); try (Connection conn = ProvDbUtils.getInstance().getConnection(); - PreparedStatement ps = conn.prepareStatement("select * from PARAMETERS")) { - ResultSet rs = ps.executeQuery(); + PreparedStatement ps = conn.prepareStatement("select * from PARAMETERS"); + ResultSet rs = ps.executeQuery()) { while (rs.next()) { Parameters param = new Parameters(rs); coll.add(param); @@ -132,9 +132,10 @@ public class Parameters extends Syncable { PreparedStatement stmt = conn.prepareStatement( "select KEYNAME, VALUE from PARAMETERS where KEYNAME = ?")) { stmt.setString(1, key); - ResultSet rs = stmt.executeQuery(); - if (rs.next()) { - val = new Parameters(rs); + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + val = new Parameters(rs); + } } } catch (SQLException e) { intlogger.error(SQLEXCEPTION + e.getMessage(), e); diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/AafPropsUtils.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/AafPropsUtils.java index 68981599..6b78d21d 100644 --- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/AafPropsUtils.java +++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/AafPropsUtils.java @@ -29,10 +29,8 @@ import org.onap.aaf.cadi.PropAccess; public class AafPropsUtils { - private static AafPropsUtils aafPropsUtilsInstance = null; private static EELFLogger eelfLogger = EELFManager.getInstance().getLogger(AafPropsUtils.class); - public static final String DEFAULT_TRUSTSTORE = "/opt/app/osaaf/local/org.onap.dmaap-dr.trust.jks"; public static final String KEYSTORE_TYPE_PROPERTY = "PKCS12"; public static final String TRUESTSTORE_TYPE_PROPERTY = "jks"; private static final String KEYSTORE_PATH_PROPERTY = "cadi_keystore"; @@ -42,7 +40,7 @@ public class AafPropsUtils { private PropAccess propAccess; - private AafPropsUtils(File propsFile) throws IOException { + public AafPropsUtils(File propsFile) throws IOException { propAccess = new PropAccess(); try { propAccess.load(new FileInputStream(propsFile)); @@ -52,20 +50,6 @@ public class AafPropsUtils { } } - public static synchronized void init(File propsFile) throws IOException { - if (aafPropsUtilsInstance != null) { - throw new IllegalStateException("Already initialized"); - } - aafPropsUtilsInstance = new AafPropsUtils(propsFile); - } - - public static AafPropsUtils getInstance() { - if (aafPropsUtilsInstance == null) { - throw new IllegalStateException("Call AafPropsUtils.init(File propsFile) first"); - } - return aafPropsUtilsInstance; - } - private String decryptedPass(String password) { String decryptedPass = null; try { @@ -77,9 +61,6 @@ public class AafPropsUtils { } public PropAccess getPropAccess() { - if (propAccess == null) { - throw new IllegalStateException("Call AafPropsUtils.init(File propsFile) first"); - } return propAccess; } diff --git a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DRRouteCLI.java b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DRRouteCLI.java index 187364f9..2d92276e 100644 --- a/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DRRouteCLI.java +++ b/datarouter-prov/src/main/java/org/onap/dmaap/datarouter/provisioning/utils/DRRouteCLI.java @@ -1,505 +1,506 @@ -/******************************************************************************* - * ============LICENSE_START================================================== - * * org.onap.dmaap - * * =========================================================================== - * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * * =========================================================================== - * * Licensed under the Apache License, Version 2.0 (the "License"); - * * you may not use this file except in compliance with the License. - * * You may obtain a copy of the License at - * * - * * http://www.apache.org/licenses/LICENSE-2.0 - * * - * * Unless required by applicable law or agreed to in writing, software - * * distributed under the License is distributed on an "AS IS" BASIS, - * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * * See the License for the specific language governing permissions and - * * limitations under the License. - * * ============LICENSE_END==================================================== - * * - * * ECOMP is a trademark and service mark of AT&T Intellectual Property. - * * - ******************************************************************************/ - -package org.onap.dmaap.datarouter.provisioning.utils; - -import static java.lang.System.exit; - -import com.att.eelf.configuration.EELFLogger; -import com.att.eelf.configuration.EELFManager; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.LineNumberReader; -import java.security.KeyStore; -import java.util.Arrays; -import java.util.Properties; - -import javax.servlet.http.HttpServletResponse; - -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.StatusLine; -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.conn.scheme.Scheme; -import org.apache.http.conn.ssl.SSLSocketFactory; -import org.apache.http.impl.client.AbstractHttpClient; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.util.EntityUtils; -import org.json.JSONArray; -import org.json.JSONObject; -import org.json.JSONTokener; -import org.onap.dmaap.datarouter.provisioning.ProvRunner; - -/** - * This class provides a Command Line Interface for the routing tables in the DR Release 2.0 DB. - * A full description of this command is here. - * - * @author Robert Eby - * @version $Id: DRRouteCLI.java,v 1.2 2013/11/05 15:54:16 eby Exp $ - */ -public class DRRouteCLI { - /** - * Invoke the CLI. The CLI can be run with a single command (given as command line arguments), - * or in an interactive mode where the user types a sequence of commands to the program. The CLI is invoked via: - *

-     * java org.onap.dmaap.datarouter.provisioning.utils.DRRouteCLI [ -s server ] [ command ]
-     * 
- * A full description of the arguments to this command are - * here. - * - * @param args command line arguments - * @throws Exception for any unrecoverable problem - */ - public static void main(String[] args) throws Exception { - String server = System.getenv(ENV_VAR); - if (args.length >= 2 && args[0].equals("-s")) { - server = args[1]; - String[] str = new String[args.length - 2]; - if (str.length > 0) { - System.arraycopy(args, 2, str, 0, str.length); - } - args = str; - } - if (server == null || server.equals("")) { - System.err.println("dr-route: you need to specify a server, either via $PROVSRVR or the '-s' option."); - System.exit(1); - } - DRRouteCLI cli = new DRRouteCLI(server); - if (args.length > 0) { - boolean bool = cli.runCommand(args); - System.exit(bool ? 0 : 1); - } else { - cli.interactive(); - System.exit(0); - } - } - - private static final String ENV_VAR = "PROVSRVR"; - private static final String PROMPT = "dr-route> "; - private static final String DEFAULT_TRUSTSTORE_PATH = /* $JAVA_HOME + */ "/jre/lib/security/cacerts"; - private static final EELFLogger intlogger = EELFManager.getInstance().getLogger("InternalLog"); - - private final String server; - private int width = 120; // screen width (for list) - private AbstractHttpClient httpclient; - - /** - * Create a DRRouteCLI object connecting to the specified server. - * - * @param server the server to send command to - * @throws Exception generic exception - */ - public DRRouteCLI(String server) throws Exception { - this.server = server; - this.httpclient = new DefaultHttpClient(); - - Properties provProperties = ProvRunner.getProvProperties(); - try { - AafPropsUtils.init(new File(provProperties.getProperty( - "org.onap.dmaap.datarouter.provserver.aafprops.path", - "/opt/app/osaaf/local/org.onap.dmaap-dr.props"))); - } catch (IOException e) { - intlogger.error("NODE0314 Failed to load AAF props. Exiting", e); - exit(1); - } - - String truststoreFile = AafPropsUtils.getInstance().getTruststorePathProperty(); - String truststorePw = AafPropsUtils.getInstance().getTruststorePassProperty(); - - KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); - if (truststoreFile == null || truststoreFile.equals("")) { - String jhome = System.getenv("JAVA_HOME"); - if (jhome == null || jhome.equals("")) { - jhome = "/opt/java/jdk/jdk180"; - } - truststoreFile = jhome + DEFAULT_TRUSTSTORE_PATH; - } - File file = new File(truststoreFile); - if (file.exists()) { - FileInputStream instream = new FileInputStream(file); - try { - trustStore.load(instream, truststorePw.toCharArray()); - } catch (Exception x) { - intlogger.error("Problem reading truststore: " + x.getMessage(), x); - throw x; - } finally { - try { - instream.close(); - } catch (Exception e) { - intlogger.error("Ignore error closing input stream: " + e.getMessage(), e); - } - } - } - - SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore); - Scheme sch = new Scheme("https", 443, socketFactory); - httpclient.getConnectionManager().getSchemeRegistry().register(sch); - } - - private void interactive() throws IOException { - LineNumberReader in = new LineNumberReader(new InputStreamReader(System.in)); - while (true) { - System.out.print(PROMPT); - String line = in.readLine(); - if (line == null) { - return; - } - line = line.trim(); - if (line.equalsIgnoreCase("exit")) { // "exit" may only be used in interactive mode - return; - } - if (line.equalsIgnoreCase("quit")) { // "quit" may only be used in interactive mode - return; - } - String[] args = line.split("[ \t]+"); - if (args.length > 0) { - runCommand(args); - } - } - } - - /** - * Run the command specified by the arguments. - * - * @param args The command line arguments. - * @return true if the command was valid and succeeded - */ - boolean runCommand(String[] args) { - String cmd = args[0].trim().toLowerCase(); - if (cmd.equals("add")) { - if (args.length > 2) { - if (args[1].startsWith("in") && args.length >= 6) { - return addIngress(args); - } - if (args[1].startsWith("eg") && args.length == 4) { - return addEgress(args); - } - if (args[1].startsWith("ne") && args.length == 5) { - return addRoute(args); - } - } - System.err.println("Add command should be one of:"); - System.err.println(" add in[gress] feedid user subnet nodepatt [ seq ]"); - System.err.println(" add eg[ress] subid node"); - System.err.println(" add ne[twork] fromnode tonode vianode"); - } else if (cmd.startsWith("del")) { - if (args.length > 2) { - if (args[1].startsWith("in") && args.length == 5) { - return delIngress(args); - } - if (args[1].startsWith("in") && args.length == 3) { - return delIngress(args); - } - if (args[1].startsWith("eg") && args.length == 3) { - return delEgress(args); - } - if (args[1].startsWith("ne") && args.length == 4) { - return delRoute(args); - } - } - System.err.println("Delete command should be one of:"); - System.err.println(" del in[gress] feedid user subnet"); - System.err.println(" del in[gress] seq"); - System.err.println(" del eg[ress] subid"); - System.err.println(" del ne[twork] fromnode tonode"); - } else if (cmd.startsWith("lis")) { - return list(args); - } else if (cmd.startsWith("wid") && args.length > 1) { - width = Integer.parseInt(args[1]); - return true; - } else if (cmd.startsWith("?") || cmd.startsWith("hel") || cmd.startsWith("usa")) { - usage(); - } else if (cmd.startsWith("#")) { - // comment -- ignore - } else { - System.err.println("Command should be one of add, del, list, exit, quit"); - } - return false; - } - - private void usage() { - System.out.println("Enter one of the following commands:"); - System.out.println(" add in[gress] feedid user subnet nodepatt [ seq ]"); - System.out.println(" add eg[ress] subid node"); - System.out.println(" add ne[twork] fromnode tonode vianode"); - System.out.println(" del in[gress] feedid user subnet"); - System.out.println(" del in[gress] seq"); - System.out.println(" del eg[ress] subid"); - System.out.println(" del ne[twork] fromnode tonode"); - System.out.println(" list [ all | ingress | egress | network ]"); - System.out.println(" exit"); - System.out.println(" quit"); - } - - private boolean addIngress(String[] args) { - String url = String.format("https://%s/internal/route/ingress/?feed=%s&user=%s&subnet=%s&nodepatt=%s", server, args[2], args[3], args[4], args[5]); - if (args.length > 6) { - url += "&seq=" + args[6]; - } - return doPost(url); - } - - private boolean addEgress(String[] args) { - String url = String.format("https://%s/internal/route/egress/?sub=%s&node=%s", server, args[2], args[3]); - return doPost(url); - } - - private boolean addRoute(String[] args) { - String url = String.format("https://%s/internal/route/network/?from=%s&to=%s&via=%s", server, args[2], args[3], args[4]); - return doPost(url); - } - - private boolean delIngress(String[] args) { - String url; - if (args.length == 5) { - String subnet = args[4].replaceAll("/", "!"); // replace the / with a ! - url = String.format("https://%s/internal/route/ingress/%s/%s/%s", server, args[2], args[3], subnet); - } else { - url = String.format("https://%s/internal/route/ingress/%s", server, args[2]); - } - return doDelete(url); - } - - private boolean delEgress(String[] args) { - String url = String.format("https://%s/internal/route/egress/%s", server, args[2]); - return doDelete(url); - } - - private boolean delRoute(String[] args) { - String url = String.format("https://%s/internal/route/network/%s/%s", server, args[2], args[3]); - return doDelete(url); - } - - private boolean list(String[] args) { - String tbl = (args.length == 1) ? "all" : args[1].toLowerCase(); - JSONObject jo = doGet("https://" + server + "/internal/route/"); // Returns all 3 tables - StringBuilder sb = new StringBuilder(); - if (tbl.startsWith("al") || tbl.startsWith("in")) { - // Display the IRT - JSONArray irt = jo.optJSONArray("ingress"); - int cw1 = 6; - int cw2 = 6; - int cw3 = 6; - int cw4 = 6; // determine column widths for first 4 cols - for (int i = 0; irt != null && i < irt.length(); i++) { - JSONObject jsonObject = irt.getJSONObject(i); - cw1 = Math.max(cw1, ("" + jsonObject.getInt("seq")).length()); - cw2 = Math.max(cw2, ("" + jsonObject.getInt("feedid")).length()); - String str = jsonObject.optString("user"); - cw3 = Math.max(cw3, (str == null) ? 1 : str.length()); - str = jsonObject.optString("subnet"); - cw4 = Math.max(cw4, (str == null) ? 1 : str.length()); - } - - int nblank = cw1 + cw2 + cw3 + cw4 + 8; - sb.append("Ingress Routing Table\n"); - sb.append(String.format("%s %s %s %s Nodes\n", ext("Seq", cw1), - ext("FeedID", cw2), ext("User", cw3), ext("Subnet", cw4))); - for (int i = 0; irt != null && i < irt.length(); i++) { - JSONObject jsonObject = irt.getJSONObject(i); - String seq = "" + jsonObject.getInt("seq"); - String feedid = "" + jsonObject.getInt("feedid"); - String user = jsonObject.optString("user"); - String subnet = jsonObject.optString("subnet"); - if (user.equals("")) { - user = "-"; - } - if (subnet.equals("")) { - subnet = "-"; - } - JSONArray nodes = jsonObject.getJSONArray("node"); - int sol = sb.length(); - sb.append(String.format("%s %s %s %s ", ext(seq, cw1), - ext(feedid, cw2), ext(user, cw3), ext(subnet, cw4))); - for (int j = 0; j < nodes.length(); j++) { - String nd = nodes.getString(j); - int cursor = sb.length() - sol; - if (j > 0 && (cursor + nd.length() > width)) { - sb.append("\n"); - sol = sb.length(); - sb.append(ext(" ", nblank)); - } - sb.append(nd); - if ((j + 1) < nodes.length()) { - sb.append(", "); - } - } - sb.append("\n"); - } - } - if (tbl.startsWith("al") || tbl.startsWith("eg")) { - // Display the ERT - JSONObject ert = jo.optJSONObject("egress"); - String[] subs = (ert == null) ? new String[0] : JSONObject.getNames(ert); - if (subs == null) { - subs = new String[0]; - } - Arrays.sort(subs); - int cw1 = 5; - for (int i = 0; i < subs.length; i++) { - cw1 = Math.max(cw1, subs[i].length()); - } - - if (sb.length() > 0) { - sb.append("\n"); - } - sb.append("Egress Routing Table\n"); - sb.append(String.format("%s Node\n", ext("SubID", cw1))); - for (int i = 0; i < subs.length; i++) { - if (ert != null && ert.length() != 0 ) { - String node = ert.getString(subs[i]); - sb.append(String.format("%s %s\n", ext(subs[i], cw1), node)); - } - - } - } - if (tbl.startsWith("al") || tbl.startsWith("ne")) { - // Display the NRT - JSONArray nrt = jo.optJSONArray("routing"); - int cw1 = 4; - int cw2 = 4; - for (int i = 0; nrt != null && i < nrt.length(); i++) { - JSONObject jsonObject = nrt.getJSONObject(i); - String from = jsonObject.getString("from"); - String to = jsonObject.getString("to"); - cw1 = Math.max(cw1, from.length()); - cw2 = Math.max(cw2, to.length()); - } - - if (sb.length() > 0) { - sb.append("\n"); - } - sb.append("Network Routing Table\n"); - sb.append(String.format("%s %s Via\n", ext("From", cw1), ext("To", cw2))); - for (int i = 0; nrt != null && i < nrt.length(); i++) { - JSONObject jsonObject = nrt.getJSONObject(i); - String from = jsonObject.getString("from"); - String to = jsonObject.getString("to"); - String via = jsonObject.getString("via"); - sb.append(String.format("%s %s %s\n", ext(from, cw1), ext(to, cw2), via)); - } - } - System.out.print(sb.toString()); - return true; - } - - private String ext(String str, int num) { - if (str == null) { - str = "-"; - } - while (str.length() < num) { - str += " "; - } - return str; - } - - private boolean doDelete(String url) { - boolean rv = false; - HttpDelete meth = new HttpDelete(url); - try { - HttpResponse response = httpclient.execute(meth); - HttpEntity entity = response.getEntity(); - StatusLine sl = response.getStatusLine(); - rv = (sl.getStatusCode() == HttpServletResponse.SC_OK); - if (rv) { - System.out.println("Routing entry deleted."); - EntityUtils.consume(entity); - } else { - printErrorText(entity); - } - } catch (Exception e) { - intlogger.error("PROV0006 doDelete: " + e.getMessage(), e); - } finally { - meth.releaseConnection(); - } - return rv; - } - - private JSONObject doGet(String url) { - JSONObject rv = new JSONObject(); - HttpGet meth = new HttpGet(url); - try { - HttpResponse response = httpclient.execute(meth); - HttpEntity entity = response.getEntity(); - StatusLine sl = response.getStatusLine(); - if (sl.getStatusCode() == HttpServletResponse.SC_OK) { - rv = new JSONObject(new JSONTokener(entity.getContent())); - } else { - printErrorText(entity); - } - } catch (Exception e) { - intlogger.error("PROV0005 doGet: " + e.getMessage(), e); - } finally { - meth.releaseConnection(); - } - return rv; - } - - private boolean doPost(String url) { - boolean rv = false; - HttpPost meth = new HttpPost(url); - try { - HttpResponse response = httpclient.execute(meth); - HttpEntity entity = response.getEntity(); - StatusLine sl = response.getStatusLine(); - rv = (sl.getStatusCode() == HttpServletResponse.SC_OK); - if (rv) { - System.out.println("Routing entry added."); - EntityUtils.consume(entity); - } else { - printErrorText(entity); - } - } catch (Exception e) { - intlogger.error("PROV0009 doPost: " + e.getMessage(), e); - } finally { - meth.releaseConnection(); - } - return rv; - } - - private void printErrorText(HttpEntity entity) throws IOException { - // Look for and print only the part of the output between
...
- InputStream is = entity.getContent(); - StringBuilder sb = new StringBuilder(); - byte[] bite = new byte[512]; - int num; - while ((num = is.read(bite)) > 0) { - sb.append(new String(bite, 0, num)); - } - is.close(); - int ix = sb.indexOf("
");
-        if (ix > 0) {
-            sb.delete(0, ix + 5);
-        }
-        ix = sb.indexOf("
"); - if (ix > 0) { - sb.delete(ix, sb.length()); - } - System.err.println(sb.toString()); - } -} +/******************************************************************************* + * ============LICENSE_START================================================== + * * org.onap.dmaap + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ + +package org.onap.dmaap.datarouter.provisioning.utils; + +import static java.lang.System.exit; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.security.KeyStore; +import java.util.Arrays; +import java.util.Properties; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.conn.scheme.Scheme; +import org.apache.http.conn.ssl.SSLSocketFactory; +import org.apache.http.impl.client.AbstractHttpClient; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.util.EntityUtils; +import org.json.JSONArray; +import org.json.JSONObject; +import org.json.JSONTokener; +import org.onap.dmaap.datarouter.provisioning.ProvRunner; + +/** + * This class provides a Command Line Interface for the routing tables in the DR Release 2.0 DB. + * A full description of this command is here. + * + * @author Robert Eby + * @version $Id: DRRouteCLI.java,v 1.2 2013/11/05 15:54:16 eby Exp $ + */ +public class DRRouteCLI { + /** + * Invoke the CLI. The CLI can be run with a single command (given as command line arguments), + * or in an interactive mode where the user types a sequence of commands to the program. The CLI is invoked via: + *
+     * java org.onap.dmaap.datarouter.provisioning.utils.DRRouteCLI [ -s server ] [ command ]
+     * 
+ * A full description of the arguments to this command are + * here. + * + * @param args command line arguments + * @throws Exception for any unrecoverable problem + */ + public static void main(String[] args) throws Exception { + String server = System.getenv(ENV_VAR); + if (args.length >= 2 && args[0].equals("-s")) { + server = args[1]; + String[] str = new String[args.length - 2]; + if (str.length > 0) { + System.arraycopy(args, 2, str, 0, str.length); + } + args = str; + } + if (server == null || server.equals("")) { + System.err.println("dr-route: you need to specify a server, either via $PROVSRVR or the '-s' option."); + System.exit(1); + } + DRRouteCLI cli = new DRRouteCLI(server); + if (args.length > 0) { + boolean bool = cli.runCommand(args); + System.exit(bool ? 0 : 1); + } else { + cli.interactive(); + System.exit(0); + } + } + + private static final String ENV_VAR = "PROVSRVR"; + private static final String PROMPT = "dr-route> "; + private static final String DEFAULT_TRUSTSTORE_PATH = /* $JAVA_HOME + */ "/jre/lib/security/cacerts"; + private static final EELFLogger intlogger = EELFManager.getInstance().getLogger("InternalLog"); + + private final String server; + private int width = 120; // screen width (for list) + private AbstractHttpClient httpclient; + + /** + * Create a DRRouteCLI object connecting to the specified server. + * + * @param server the server to send command to + * @throws Exception generic exception + */ + public DRRouteCLI(String server) throws Exception { + this.server = server; + this.httpclient = new DefaultHttpClient(); + AafPropsUtils aafPropsUtils = null; + + Properties provProperties = ProvRunner.getProvProperties(); + try { + aafPropsUtils = new AafPropsUtils(new File(provProperties.getProperty( + "org.onap.dmaap.datarouter.provserver.aafprops.path", + "/opt/app/osaaf/local/org.onap.dmaap-dr.props"))); + } catch (IOException e) { + intlogger.error("NODE0314 Failed to load AAF props. Exiting", e); + exit(1); + } + + String truststoreFile = aafPropsUtils.getTruststorePathProperty(); + String truststorePw = aafPropsUtils.getTruststorePassProperty(); + + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + if (truststoreFile == null || truststoreFile.equals("")) { + String jhome = System.getenv("JAVA_HOME"); + if (jhome == null || jhome.equals("")) { + jhome = "/opt/java/jdk/jdk180"; + } + truststoreFile = jhome + DEFAULT_TRUSTSTORE_PATH; + } + File file = new File(truststoreFile); + if (file.exists()) { + FileInputStream instream = new FileInputStream(file); + try { + trustStore.load(instream, truststorePw.toCharArray()); + } catch (Exception x) { + intlogger.error("Problem reading truststore: " + x.getMessage(), x); + throw x; + } finally { + try { + instream.close(); + } catch (Exception e) { + intlogger.error("Ignore error closing input stream: " + e.getMessage(), e); + } + } + } + + SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore); + Scheme sch = new Scheme("https", 443, socketFactory); + httpclient.getConnectionManager().getSchemeRegistry().register(sch); + } + + private void interactive() throws IOException { + LineNumberReader in = new LineNumberReader(new InputStreamReader(System.in)); + while (true) { + System.out.print(PROMPT); + String line = in.readLine(); + if (line == null) { + return; + } + line = line.trim(); + if (line.equalsIgnoreCase("exit")) { // "exit" may only be used in interactive mode + return; + } + if (line.equalsIgnoreCase("quit")) { // "quit" may only be used in interactive mode + return; + } + String[] args = line.split("[ \t]+"); + if (args.length > 0) { + runCommand(args); + } + } + } + + /** + * Run the command specified by the arguments. + * + * @param args The command line arguments. + * @return true if the command was valid and succeeded + */ + boolean runCommand(String[] args) { + String cmd = args[0].trim().toLowerCase(); + if (cmd.equals("add")) { + if (args.length > 2) { + if (args[1].startsWith("in") && args.length >= 6) { + return addIngress(args); + } + if (args[1].startsWith("eg") && args.length == 4) { + return addEgress(args); + } + if (args[1].startsWith("ne") && args.length == 5) { + return addRoute(args); + } + } + System.err.println("Add command should be one of:"); + System.err.println(" add in[gress] feedid user subnet nodepatt [ seq ]"); + System.err.println(" add eg[ress] subid node"); + System.err.println(" add ne[twork] fromnode tonode vianode"); + } else if (cmd.startsWith("del")) { + if (args.length > 2) { + if (args[1].startsWith("in") && args.length == 5) { + return delIngress(args); + } + if (args[1].startsWith("in") && args.length == 3) { + return delIngress(args); + } + if (args[1].startsWith("eg") && args.length == 3) { + return delEgress(args); + } + if (args[1].startsWith("ne") && args.length == 4) { + return delRoute(args); + } + } + System.err.println("Delete command should be one of:"); + System.err.println(" del in[gress] feedid user subnet"); + System.err.println(" del in[gress] seq"); + System.err.println(" del eg[ress] subid"); + System.err.println(" del ne[twork] fromnode tonode"); + } else if (cmd.startsWith("lis")) { + return list(args); + } else if (cmd.startsWith("wid") && args.length > 1) { + width = Integer.parseInt(args[1]); + return true; + } else if (cmd.startsWith("?") || cmd.startsWith("hel") || cmd.startsWith("usa")) { + usage(); + } else if (cmd.startsWith("#")) { + // comment -- ignore + } else { + System.err.println("Command should be one of add, del, list, exit, quit"); + } + return false; + } + + private void usage() { + System.out.println("Enter one of the following commands:"); + System.out.println(" add in[gress] feedid user subnet nodepatt [ seq ]"); + System.out.println(" add eg[ress] subid node"); + System.out.println(" add ne[twork] fromnode tonode vianode"); + System.out.println(" del in[gress] feedid user subnet"); + System.out.println(" del in[gress] seq"); + System.out.println(" del eg[ress] subid"); + System.out.println(" del ne[twork] fromnode tonode"); + System.out.println(" list [ all | ingress | egress | network ]"); + System.out.println(" exit"); + System.out.println(" quit"); + } + + private boolean addIngress(String[] args) { + String url = String.format("https://%s/internal/route/ingress/?feed=%s&user=%s&subnet=%s&nodepatt=%s", server, args[2], args[3], args[4], args[5]); + if (args.length > 6) { + url += "&seq=" + args[6]; + } + return doPost(url); + } + + private boolean addEgress(String[] args) { + String url = String.format("https://%s/internal/route/egress/?sub=%s&node=%s", server, args[2], args[3]); + return doPost(url); + } + + private boolean addRoute(String[] args) { + String url = String.format("https://%s/internal/route/network/?from=%s&to=%s&via=%s", server, args[2], args[3], args[4]); + return doPost(url); + } + + private boolean delIngress(String[] args) { + String url; + if (args.length == 5) { + String subnet = args[4].replaceAll("/", "!"); // replace the / with a ! + url = String.format("https://%s/internal/route/ingress/%s/%s/%s", server, args[2], args[3], subnet); + } else { + url = String.format("https://%s/internal/route/ingress/%s", server, args[2]); + } + return doDelete(url); + } + + private boolean delEgress(String[] args) { + String url = String.format("https://%s/internal/route/egress/%s", server, args[2]); + return doDelete(url); + } + + private boolean delRoute(String[] args) { + String url = String.format("https://%s/internal/route/network/%s/%s", server, args[2], args[3]); + return doDelete(url); + } + + private boolean list(String[] args) { + String tbl = (args.length == 1) ? "all" : args[1].toLowerCase(); + JSONObject jo = doGet("https://" + server + "/internal/route/"); // Returns all 3 tables + StringBuilder sb = new StringBuilder(); + if (tbl.startsWith("al") || tbl.startsWith("in")) { + // Display the IRT + JSONArray irt = jo.optJSONArray("ingress"); + int cw1 = 6; + int cw2 = 6; + int cw3 = 6; + int cw4 = 6; // determine column widths for first 4 cols + for (int i = 0; irt != null && i < irt.length(); i++) { + JSONObject jsonObject = irt.getJSONObject(i); + cw1 = Math.max(cw1, ("" + jsonObject.getInt("seq")).length()); + cw2 = Math.max(cw2, ("" + jsonObject.getInt("feedid")).length()); + String str = jsonObject.optString("user"); + cw3 = Math.max(cw3, (str == null) ? 1 : str.length()); + str = jsonObject.optString("subnet"); + cw4 = Math.max(cw4, (str == null) ? 1 : str.length()); + } + + int nblank = cw1 + cw2 + cw3 + cw4 + 8; + sb.append("Ingress Routing Table\n"); + sb.append(String.format("%s %s %s %s Nodes\n", ext("Seq", cw1), + ext("FeedID", cw2), ext("User", cw3), ext("Subnet", cw4))); + for (int i = 0; irt != null && i < irt.length(); i++) { + JSONObject jsonObject = irt.getJSONObject(i); + String seq = "" + jsonObject.getInt("seq"); + String feedid = "" + jsonObject.getInt("feedid"); + String user = jsonObject.optString("user"); + String subnet = jsonObject.optString("subnet"); + if (user.equals("")) { + user = "-"; + } + if (subnet.equals("")) { + subnet = "-"; + } + JSONArray nodes = jsonObject.getJSONArray("node"); + int sol = sb.length(); + sb.append(String.format("%s %s %s %s ", ext(seq, cw1), + ext(feedid, cw2), ext(user, cw3), ext(subnet, cw4))); + for (int j = 0; j < nodes.length(); j++) { + String nd = nodes.getString(j); + int cursor = sb.length() - sol; + if (j > 0 && (cursor + nd.length() > width)) { + sb.append("\n"); + sol = sb.length(); + sb.append(ext(" ", nblank)); + } + sb.append(nd); + if ((j + 1) < nodes.length()) { + sb.append(", "); + } + } + sb.append("\n"); + } + } + if (tbl.startsWith("al") || tbl.startsWith("eg")) { + // Display the ERT + JSONObject ert = jo.optJSONObject("egress"); + String[] subs = (ert == null) ? new String[0] : JSONObject.getNames(ert); + if (subs == null) { + subs = new String[0]; + } + Arrays.sort(subs); + int cw1 = 5; + for (int i = 0; i < subs.length; i++) { + cw1 = Math.max(cw1, subs[i].length()); + } + + if (sb.length() > 0) { + sb.append("\n"); + } + sb.append("Egress Routing Table\n"); + sb.append(String.format("%s Node\n", ext("SubID", cw1))); + for (int i = 0; i < subs.length; i++) { + if (ert != null && ert.length() != 0 ) { + String node = ert.getString(subs[i]); + sb.append(String.format("%s %s\n", ext(subs[i], cw1), node)); + } + + } + } + if (tbl.startsWith("al") || tbl.startsWith("ne")) { + // Display the NRT + JSONArray nrt = jo.optJSONArray("routing"); + int cw1 = 4; + int cw2 = 4; + for (int i = 0; nrt != null && i < nrt.length(); i++) { + JSONObject jsonObject = nrt.getJSONObject(i); + String from = jsonObject.getString("from"); + String to = jsonObject.getString("to"); + cw1 = Math.max(cw1, from.length()); + cw2 = Math.max(cw2, to.length()); + } + + if (sb.length() > 0) { + sb.append("\n"); + } + sb.append("Network Routing Table\n"); + sb.append(String.format("%s %s Via\n", ext("From", cw1), ext("To", cw2))); + for (int i = 0; nrt != null && i < nrt.length(); i++) { + JSONObject jsonObject = nrt.getJSONObject(i); + String from = jsonObject.getString("from"); + String to = jsonObject.getString("to"); + String via = jsonObject.getString("via"); + sb.append(String.format("%s %s %s\n", ext(from, cw1), ext(to, cw2), via)); + } + } + System.out.print(sb.toString()); + return true; + } + + private String ext(String str, int num) { + if (str == null) { + str = "-"; + } + while (str.length() < num) { + str += " "; + } + return str; + } + + private boolean doDelete(String url) { + boolean rv = false; + HttpDelete meth = new HttpDelete(url); + try { + HttpResponse response = httpclient.execute(meth); + HttpEntity entity = response.getEntity(); + StatusLine sl = response.getStatusLine(); + rv = (sl.getStatusCode() == HttpServletResponse.SC_OK); + if (rv) { + System.out.println("Routing entry deleted."); + EntityUtils.consume(entity); + } else { + printErrorText(entity); + } + } catch (Exception e) { + intlogger.error("PROV0006 doDelete: " + e.getMessage(), e); + } finally { + meth.releaseConnection(); + } + return rv; + } + + private JSONObject doGet(String url) { + JSONObject rv = new JSONObject(); + HttpGet meth = new HttpGet(url); + try { + HttpResponse response = httpclient.execute(meth); + HttpEntity entity = response.getEntity(); + StatusLine sl = response.getStatusLine(); + if (sl.getStatusCode() == HttpServletResponse.SC_OK) { + rv = new JSONObject(new JSONTokener(entity.getContent())); + } else { + printErrorText(entity); + } + } catch (Exception e) { + intlogger.error("PROV0005 doGet: " + e.getMessage(), e); + } finally { + meth.releaseConnection(); + } + return rv; + } + + private boolean doPost(String url) { + boolean rv = false; + HttpPost meth = new HttpPost(url); + try { + HttpResponse response = httpclient.execute(meth); + HttpEntity entity = response.getEntity(); + StatusLine sl = response.getStatusLine(); + rv = (sl.getStatusCode() == HttpServletResponse.SC_OK); + if (rv) { + System.out.println("Routing entry added."); + EntityUtils.consume(entity); + } else { + printErrorText(entity); + } + } catch (Exception e) { + intlogger.error("PROV0009 doPost: " + e.getMessage(), e); + } finally { + meth.releaseConnection(); + } + return rv; + } + + private void printErrorText(HttpEntity entity) throws IOException { + // Look for and print only the part of the output between
...
+ InputStream is = entity.getContent(); + StringBuilder sb = new StringBuilder(); + byte[] bite = new byte[512]; + int num; + while ((num = is.read(bite)) > 0) { + sb.append(new String(bite, 0, num)); + } + is.close(); + int ix = sb.indexOf("
");
+        if (ix > 0) {
+            sb.delete(0, ix + 5);
+        }
+        ix = sb.indexOf("
"); + if (ix > 0) { + sb.delete(ix, sb.length()); + } + System.err.println(sb.toString()); + } +} diff --git a/datarouter-prov/src/main/resources/logback.xml b/datarouter-prov/src/main/resources/logback.xml index afa4df74..b294e73d 100644 --- a/datarouter-prov/src/main/resources/logback.xml +++ b/datarouter-prov/src/main/resources/logback.xml @@ -310,7 +310,7 @@ - 5MB + 50MB ${jettyLoggerPattern} @@ -364,7 +364,7 @@ - + @@ -400,7 +400,7 @@ - + diff --git a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/ProvServerTest.java b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/ProvServerTest.java new file mode 100644 index 00000000..78d2eaa7 --- /dev/null +++ b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/ProvServerTest.java @@ -0,0 +1,57 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.dmaap.datarouter.provisioning; + +import java.io.File; +import java.io.IOException; +import org.apache.commons.lang3.reflect.FieldUtils; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.dmaap.datarouter.provisioning.utils.AafPropsUtils; + +public class ProvServerTest { + + private AafPropsUtils aafPropsUtils; + + @Before + public void setUp() { + try { + aafPropsUtils = new AafPropsUtils(new File("src/test/resources/aaf/org.onap.dmaap-dr.props")); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @BeforeClass + public static void init() { + System.setProperty( + "org.onap.dmaap.datarouter.provserver.properties", + "src/test/resources/h2Database.properties"); + } + + @Test + public void Verify_Prov_Server_Is_Configured_Correctly() throws IllegalAccessException { + FieldUtils.writeDeclaredStaticField(ProvRunner.class, "aafPropsUtils", aafPropsUtils, true); + Assert.assertNotNull(ProvServer.getServerInstance()); + } +} diff --git a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/utils/AafPropsUtilsTest.java b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/utils/AafPropsUtilsTest.java index 09d4a819..64c5e492 100644 --- a/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/utils/AafPropsUtilsTest.java +++ b/datarouter-prov/src/test/java/org/onap/dmaap/datarouter/provisioning/utils/AafPropsUtilsTest.java @@ -32,8 +32,7 @@ public class AafPropsUtilsTest { @BeforeClass public static void init() throws Exception { - AafPropsUtils.init(new File("src/test/resources/aaf/org.onap.dmaap-dr.props")); - aafPropsUtils = AafPropsUtils.getInstance(); + aafPropsUtils = new AafPropsUtils(new File("src/test/resources/aaf/org.onap.dmaap-dr.props")); } @Test diff --git a/datarouter-prov/src/test/resources/aaf/org.onap.dmaap-dr.p12 b/datarouter-prov/src/test/resources/aaf/org.onap.dmaap-dr.p12 new file mode 100644 index 0000000000000000000000000000000000000000..bd60d26e2e2cb16b9b33f395c683e7f912aa76af GIT binary patch literal 4233 zcmZXUcQhLgyT=m}s}!ld_ihDk?HEN7ql6eWTB9~ajjE!tckI1dYHzhy?7fwmHOkLk zB|>rg-gEDL&wK89&NI&E`#jH|Unq(q7!QaKMNz;Ahy_AaL$G8(LSQb6LKuXi5d4dI zp(t?1e@Ngc5DFaj7YF^#0D^n}b45x5#LGp2uAwLp7RpaR^1t}+b4Cyq-wtcf+ksV? z;R5%slCg|V^8utq&qvbu_6mie$^6aNnMp=^>lI8E>YFNvXO0BV|(Vkr#ygR zq%}YlA%9G>F<5Unr+tE7_pzKJE7CdKMpXS!s_141?~ZmN%*^t#SWe1NTb1XRd4JPp zrlnqdoy&xNHMuD1OO|MEs%5_l2@kAAdqnAtAVNqt?!(pWZLT)Po4TQr!@W$!>8Zq+ zLE@PL1^1gQ2rA;^xM!URM!P>^ad#G_-&`)pFV)h7yFzLKk#VbDHp7h1kInG25`Vcy z$O2;*$>)w4G;6h5Lat-mkQp<+2DH&H6@1XGN@7(ww8MT&_lI^G33lQnbn@BCGLY6Q zJ0EeLN>17F`;1@ALwB8by#)ACjGdOlB+M-!l`Q93pL>}#x9(N1uq(kWx_O(0nkgWH2`TmxM-U?&d2go`lK?{S- z7(RvQ;Z=(>)e6N+ekvIyChegY|HP(KSs}E-5h$11-_pITZ3W9+j#3;gBbt#O0-&wL z&cf@TLuLY$KC5e!W{EJ%aLfS5hJ(l?b5o3VQ@TCRa zojT}>{V`G997aw~cm_yNe@s3gfrhI9`?`&4&i_nqc8C^qzd=(gbJSX>rYr_oY@wvz z@J$dXjwcoBE6khB?zQ>Gjw%fkQU0`qV>OC330rw_%^#v(oAQK@3y~d8cU=UX7jh4H zryc#iN8g{iEZENYaEzg z3v1*K8xg`LqfqN@X80_0Ecbfk~CTLmMesVz3t>t zHuMXm%}N1@euek$Dt85|bQtbT{oYGWnV6dxbxOD#co&9vT}vOa`~K4Qa{HF~nWByt z?G)iC*GWzTB)$SDoh>|w_Ded_n~XOo*>P41&Nx^W065wtN#Q1}=7zS`R`V0z3HKso zEA!xdyH06-Ylr27sGvN8rIX_}sI`TkcH(y3A1&{4zZkL@^AlMY>`n+mN|6+He6HM8 zVl8}iv8jL#TX>S@p2-U@ads%TnpKy)cH}Vn6YHz0d_*IBmw9@v+Q#)|L}4kK zHaqoHK}W62a}(YG51Sm({!sErI`xsSivX75@}8ox{IZG#rGL(jZ{*26f-PsCh8HNd z6}6Vu=ZXqP; z%DssE_0VoK?vAxp?q1t!ywp)?kp&{S;9xW$H}I-wj#nZ~1j12?R|QecB{iT=x6C{L z25s7|dJpvxug)$bdcR&SOcB(<5hVb|C)H&G?PhOQz4&Y1$*35Cy6#ij7^?vNunRMl#mH`nAj@m+^$@9IJ+EXvVjU?1 zJjUqyFrnps(#y%|bFFmYlD9p`jm3cb<(y)UBin(;@hsLwu;gEctI2vZ7r+c&pZ<>y zNSns~f+jD13fGIxj-=9qV(S$HjU?ywlajvd&e{7H`QLSNNaNkmVW!uOTWO zcaD`4*r^$M#R-P)57f1}=-a%G_=S#1kUrus(iJMP;)HxeZCDQ1JGSV+7Xh-D#7s|$ zh1CjkIP>M^3rg}IekcATs>d!BLS!#!r)D}LW4m_!CL7mlX_Wlz^?JvET>8O93D1iw zVvhWS4B#NlN9NI3Qw@5f`{c6^lkL7jslO`uN4FZHovO^zLKp=bnVtN8QHE zQ7&Kt83Z8pSFkrUhUQt2`(rs@gboPSD$jjtV_InP{BS>1aJ>%sigo6WXhojZJneki zw1TMT=u^ba3^G!BJ60X8+}{_kw&yb!9aS(TwX;dAZz4K)vcH)dhF(0T{GG(4d;6Z* zCz`eYVExZK@G>=|%cB!4>KYWg&utt6b2efy0)-wvnbjJ6R5MRCC8Piv{PZBxi~FOf ztZ&~V2@#PSk84Raan2^AnSdAHOLUF-V@dUX`29At9Uo{UKVNH_{W;_skmqsIR+u%1*Xiq=+?8#hr`?=;f-Xpa{~y_$2K2~77UHMsagcbNC> zZ2)*w>=W4+CNs2-SFP?ieM^qXE_LkS@$Jw*nsSwT>RB`2yzZ!F_cnZdSAw)`h=VK6 z#$V0c;$d~f%>X?wn$eVP6_4;gy^D%xTt?g@F6V`piNz6v1A{3BMiAkZeNXKwRx@x7 zOX~QE(MU;JP7KbX|D<{OJXN(lRdr-a)66k_OqUDR&f?`kP48|$#??Tunt`khV~ZJ} zmGn`0{u*gymcMTaep+Z27dn$y@vXE(%w`TgV{R?{s+5`t!{wU?2rRF9P09n%(hcH-;3-PNf{ERk9JVWKAq1N#|T$Oi*@bPMBTCsDR7AGixPcFW%fR8n# zd(Ljlx;&-|yhS+U?RRW{G`eW5G5zfmY?JQ=%U{AgOkk%o z*X;}@Y?sIUPDKfE*+iU451B#7J{|qe+wemm2=^}h^XiR*R+-OhJLDI2#iKd87<>B0 z-QzDkqj)&ai>~$`mweQ}>{Cuz6!o-jl#_ zC5_zZ9HbopS7#&+`6lJ4(LY^D`a_7WQ0b1~K!lBB_iE$-CMi(9L{Bl_VB zbEsWAoI0u@+?O5Ka3U%}p03DJAs?f-6*FwuBr@DWGZZK*+BnmN3ruKyg%@MM@T*m6pl%o#w-!AK!$ue_D!8^*g51StN1g^^u^t7cZWPHFE19k z>EPxfWl8Fbmj_uIXG!?Ivu@^YI`nq!ZaUbb5_$nB)dNb?bASCH7Y}35uqdCf-W`LJ z-(_vH`ZQBF;TuH(_e-lLp#%P*)=9;Wbn|9I*s|--&eHKES*(yR@Rn$L(c9*RoB8Zf z!a~^a4{yesqS_pyjS=oSIkC!>W@fPDMu3|C(60e~4hL$po+L|W!rsy%z<~FBHx^{k zGV=3y%a3ocLyicx;t@IG9Swc_j%;oqvkU%dbPu>QST9qkH9_{l#)Ra_Epzo~Lu~o{ z2Qm$XR9TmRn`}4V^Pk<$p>G1_Ytor#8*>j9hdTqmaxuveDrjhaAM;dSo!WmX(R#F& zVf|H6H+tcglIr1t^`8+f_`s_IQkbfGS-w&pSK-DsPt}L?*Q^yPU#9QQH#zunAE@ch z%y)EFwC3gf@L0a(_Mpd8sL5FQ?CKTyGWeYVpoMO+X)sAsIG!jff&0E?i${FKdzr|q@> z7R*TGurG!dd}$bzPqk3_@`#t!?OiGj^E20Bnr~MeKOQB6wN@^!HSm+8Wv|;!xmx!~ zBIZdNrb@Rimwx=Y^q7-2Ki%i+8MICej*#KkzOE*@+@yL4!^Vbx&6{LT0n)bh9Wg1J zrLgoRkSL274LTunOw}7m(Y1N!7o_h{&(E{F=qxhkp)e>rl$Zc4cpo2+0So|9Syt^% wA2aAFzk`{pjqXH#QTv_$9z>m!4-CouFMzoQumAu6 literal 0 HcmV?d00001 diff --git a/datarouter-prov/src/test/resources/aaf/org.onap.dmaap-dr.trust.jks b/datarouter-prov/src/test/resources/aaf/org.onap.dmaap-dr.trust.jks new file mode 100644 index 0000000000000000000000000000000000000000..0c9da2e50cd7b757e572b8e92a2b82328b8a4915 GIT binary patch literal 1413 zcmb7DYdF&j9NtyOWt+8{HUI7#WhCt*&c@O40O2tARfRK~d z=U8(-BfwxqI0!HxAOR&gC=I5l1b1+@u&^Q^0L3k?pagR`Y2ipv1mw4<90o#j26n3; z2xQ;@Kq4FNRNg6#SE9WWdOWkFCNfCW*2upnSihe?Swy0(^q z3*7xUjrmAD`;s-zS=&wRtnlkvRCyh*!J0;uMXZ^VpC>kZF!ScIQ1fd0Y_R2|!UAR? zYf-T;9)EGofVa?T$7^e9Vg{qfUF?S9bls+6NWW@6p+1pg6^HapeS5u6z1|Qeubc`I zc@6tspnBp58?st&cF+1GOZBO_J{bnC67FAz56de6Emqn%Z(2$ zZ=8&GDQy)-aBp^|ZJ>OFQ!gDy1-G_3dA3R40GJY7_+fOJ-Taf-b6uCYrU153Ls7|S~(=p@3Xbrwtm)692&u- zNrgsFrZcQ*`2*2r=W1_M73+*%FaSgz!l(TS$G%M`=Gn*H`EU%WcdG@Eru=OtQ6}rF zCVi~N9_DAD#?5f;1my=K?Tm1jFVXUEhTQ$`pGHHVU=X*#9=5whS0BcmoCppql_7w*=Id0NX4G=jRx1 zwqi4eU=T&KmsuT_Z(l=E^<$W}8J_Cx*>*{0RYRJL57Z$ViC3~mpxL2v0qbZ53NlTt zATGwX$4iu^N>99;El6im_q%7dFRaV-w41d8nXL|1kDm$9@q_zJtOxsj~ZeM_3G%YNmUgr~@0&w|S|I8SrzGL4Pv2DRi*UVFeyt$JTAdRZRrR&}evp6P8eR%XReUWD# zob%~)v}F3~!%}+>T}i^8=DTaCdp-Q=3H8i5<6lzisQ$-gj+Dl`?O5%u8 z&BZg6nD6JfbkpstxG0$|Uo2qjoJuJsiPRsBM_xz0#qNrF!&`jz;-b1r2uIEYovb{w S98vS$Xw;${i|no