update DR logging to log under one system
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / onap / dmaap / datarouter / provisioning / Main.java
1 /*******************************************************************************
2  * ============LICENSE_START==================================================
3  * * org.onap.dmaap
4  * * ===========================================================================
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6  * * ===========================================================================
7  * * Licensed under the Apache License, Version 2.0 (the "License");
8  * * you may not use this file except in compliance with the License.
9  * * You may obtain a copy of the License at
10  * *
11  *  *      http://www.apache.org/licenses/LICENSE-2.0
12  * *
13  *  * Unless required by applicable law or agreed to in writing, software
14  * * distributed under the License is distributed on an "AS IS" BASIS,
15  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * * See the License for the specific language governing permissions and
17  * * limitations under the License.
18  * * ============LICENSE_END====================================================
19  * *
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  * *
22  ******************************************************************************/
23
24
25 package org.onap.dmaap.datarouter.provisioning;
26
27
28 import com.att.eelf.configuration.EELFLogger;
29 import com.att.eelf.configuration.EELFManager;
30 import org.eclipse.jetty.http.HttpVersion;
31 import org.eclipse.jetty.server.*;
32 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
33 import org.eclipse.jetty.server.handler.DefaultHandler;
34 import org.eclipse.jetty.server.handler.HandlerCollection;
35 import org.eclipse.jetty.server.handler.RequestLogHandler;
36 import org.eclipse.jetty.servlet.FilterHolder;
37 import org.eclipse.jetty.servlet.ServletContextHandler;
38 import org.eclipse.jetty.servlet.ServletHolder;
39 import org.eclipse.jetty.util.ssl.SslContextFactory;
40 import org.eclipse.jetty.util.thread.QueuedThreadPool;
41 import org.onap.aaf.cadi.PropAccess;
42 import org.onap.dmaap.datarouter.provisioning.utils.*;
43
44 import javax.servlet.DispatcherType;
45 import java.io.IOException;
46 import java.io.InputStream;
47 import java.security.Security;
48 import java.util.EnumSet;
49 import java.util.Properties;
50 import java.util.Timer;
51
52 /**
53  * <p>
54  * A main class which may be used to start the provisioning server with an "embedded" Jetty server. Configuration is
55  * done via the properties file <i>provserver.properties</i>, which should be in the CLASSPATH. The provisioning server
56  * may also be packaged with a web.xml and started as a traditional webapp.
57  * </p>
58  * <p>
59  * Most of the work of the provisioning server is carried out within the eight servlets (configured below) that are used
60  * to handle each of the eight types of requests the server may receive. In addition, there are background threads
61  * started to perform other tasks:
62  * </p>
63  * <ul>
64  * <li>One background Thread runs the {@link LogfileLoader} in order to process incoming logfiles.
65  * This Thread is created as a side effect of the first successful POST to the /internal/logs/ servlet.</li>
66  * <li>One background Thread runs the {@link SynchronizerTask} which is used to periodically
67  * synchronize the database between active and standby servers.</li>
68  * <li>One background Thread runs the {@link Poker} which is used to notify the nodes whenever
69  * provisioning data changes.</li>
70  * <li>One task is run once a day to run {@link PurgeLogDirTask} which purges older logs from the
71  * /opt/app/datartr/logs directory.</li>
72  * </ul>
73  * <p>
74  * The provisioning server is stopped by issuing a GET to the URL http://127.0.0.1/internal/halt using <i>curl</i> or
75  * some other such tool.
76  * </p>
77  *
78  * @author Robert Eby
79  * @version $Id: Main.java,v 1.12 2014/03/12 19:45:41 eby Exp $
80  */
81 public class Main {
82
83     /**
84      * The truststore to use if none is specified
85      */
86     static final String DEFAULT_TRUSTSTORE = "/opt/java/jdk/jdk180/jre/lib/security/cacerts";
87     static final String KEYSTORE_TYPE_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.type";
88     static final String KEYSTORE_PATH_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.path";
89     static final String KEYSTORE_PASS_PROPERTY = "org.onap.dmaap.datarouter.provserver.keystore.password";
90     static final String TRUSTSTORE_PATH_PROPERTY = "org.onap.dmaap.datarouter.provserver.truststore.path";
91     static final String TRUSTSTORE_PASS_PROPERTY = "org.onap.dmaap.datarouter.provserver.truststore.password";
92     public static final EELFLogger intlogger = EELFManager.getInstance().getLogger("org.onap.dmaap.datarouter.provisioning.internal");
93
94     /**
95      * The one and only {@link Server} instance in this JVM
96      */
97     private static Server server;
98
99     class Inner {
100         InputStream getCadiProps() {
101             InputStream in = null;
102             try {
103                 in = getClass().getClassLoader().getResourceAsStream("drProvCadi.properties");
104             } catch (Exception e) {
105                 intlogger.error("Exception in Main.getCadiProps() method ", e.getMessage());
106             }
107             return in;
108         }
109     }
110
111     /**
112      * Starts the Data Router Provisioning server.
113      *
114      * @param args not used
115      * @throws Exception if Jetty has a problem starting
116      */
117     public static void main(String[] args) throws Exception {
118         Security.setProperty("networkaddress.cache.ttl", "4");
119         Properties provProperties = (new DB()).getProperties();
120         // Check DB is accessible and contains the expected tables
121         if (!checkDatabase()) {
122             System.exit(1);
123         }
124
125         intlogger.info("PROV0000 **** AT&T Data Router Provisioning Server starting....");
126
127         Security.setProperty("networkaddress.cache.ttl", "4");
128         int httpPort = Integer.parseInt(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.http.port", "8080"));
129         int httpsPort = Integer.parseInt(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.https.port", "8443"));
130
131         // Server's thread pool
132         QueuedThreadPool queuedThreadPool = new QueuedThreadPool();
133         queuedThreadPool.setMinThreads(10);
134         queuedThreadPool.setMaxThreads(200);
135         queuedThreadPool.setDetailedDump(false);
136
137         // The server itself
138         server = new Server(queuedThreadPool);
139         server.setStopAtShutdown(true);
140         server.setStopTimeout(5000);
141         server.setDumpAfterStart(false);
142         server.setDumpBeforeStop(false);
143
144         // Request log configuration
145         NCSARequestLog ncsaRequestLog = new NCSARequestLog();
146         ncsaRequestLog.setFilename(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.accesslog.dir") + "/request.log.yyyy_mm_dd");
147         ncsaRequestLog.setFilenameDateFormat("yyyyMMdd");
148         ncsaRequestLog.setRetainDays(90);
149         ncsaRequestLog.setAppend(true);
150         ncsaRequestLog.setExtended(false);
151         ncsaRequestLog.setLogCookies(false);
152         ncsaRequestLog.setLogTimeZone("GMT");
153
154         RequestLogHandler requestLogHandler = new RequestLogHandler();
155         requestLogHandler.setRequestLog(ncsaRequestLog);
156         server.setRequestLog(ncsaRequestLog);
157
158         // HTTP configuration
159         HttpConfiguration httpConfiguration = new HttpConfiguration();
160         httpConfiguration.setSecureScheme("https");
161         httpConfiguration.setSecurePort(httpsPort);
162         httpConfiguration.setOutputBufferSize(32768);
163         httpConfiguration.setRequestHeaderSize(8192);
164         httpConfiguration.setResponseHeaderSize(8192);
165         httpConfiguration.setSendServerVersion(true);
166         httpConfiguration.setSendDateHeader(false);
167
168         //HTTP Connector
169         HandlerCollection handlerCollection;
170         try (ServerConnector httpServerConnector = new ServerConnector(server, new HttpConnectionFactory(httpConfiguration))) {
171             httpServerConnector.setPort(httpPort);
172             httpServerConnector.setAcceptQueueSize(2);
173             httpServerConnector.setIdleTimeout(300000);
174
175             // SSL Context
176             SslContextFactory sslContextFactory = new SslContextFactory();
177             sslContextFactory.setKeyStoreType(provProperties.getProperty(KEYSTORE_TYPE_PROPERTY, "jks"));
178             sslContextFactory.setKeyStorePath(provProperties.getProperty(KEYSTORE_PATH_PROPERTY));
179             sslContextFactory.setKeyStorePassword(provProperties.getProperty(KEYSTORE_PASS_PROPERTY));
180             sslContextFactory.setKeyManagerPassword(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.keymanager.password"));
181
182             String ts = provProperties.getProperty(TRUSTSTORE_PATH_PROPERTY);
183             if (ts != null && ts.length() > 0) {
184                 intlogger.info("@@ TS -> " + ts);
185                 sslContextFactory.setTrustStorePath(ts);
186                 sslContextFactory.setTrustStorePassword(provProperties.getProperty(TRUSTSTORE_PASS_PROPERTY));
187             } else {
188                 sslContextFactory.setTrustStorePath(DEFAULT_TRUSTSTORE);
189                 sslContextFactory.setTrustStorePassword("changeit");
190             }
191
192             sslContextFactory.setWantClientAuth(true);
193             sslContextFactory.setExcludeCipherSuites(
194                     "SSL_RSA_WITH_DES_CBC_SHA",
195                     "SSL_DHE_RSA_WITH_DES_CBC_SHA",
196                     "SSL_DHE_DSS_WITH_DES_CBC_SHA",
197                     "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
198                     "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
199                     "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
200                     "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"
201             );
202             sslContextFactory.addExcludeProtocols("SSLv3");
203             sslContextFactory.setIncludeProtocols(provProperties.getProperty(
204                     "org.onap.dmaap.datarouter.provserver.https.include.protocols", "TLSv1.1|TLSv1.2").trim().split("\\|"));
205
206             intlogger.info("Not supported protocols prov server:-" + String.join(",", sslContextFactory.getExcludeProtocols()));
207             intlogger.info("Supported protocols prov server:-" + String.join(",", sslContextFactory.getIncludeProtocols()));
208             intlogger.info("Not supported ciphers prov server:-" + String.join(",", sslContextFactory.getExcludeCipherSuites()));
209             intlogger.info("Supported ciphers prov server:-" + String.join(",", sslContextFactory.getIncludeCipherSuites()));
210
211             // HTTPS configuration
212             HttpConfiguration httpsConfiguration = new HttpConfiguration(httpConfiguration);
213             httpsConfiguration.setRequestHeaderSize(8192);
214
215             // HTTPS connector
216             try (ServerConnector httpsServerConnector = new ServerConnector(server,
217                     new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
218                     new HttpConnectionFactory(httpsConfiguration))) {
219
220                 httpsServerConnector.setPort(httpsPort);
221                 httpsServerConnector.setIdleTimeout(30000);
222                 httpsServerConnector.setAcceptQueueSize(2);
223
224                 // Servlet and Filter configuration
225                 ServletContextHandler servletContextHandler = new ServletContextHandler(0);
226                 servletContextHandler.setContextPath("/");
227                 servletContextHandler.addServlet(new ServletHolder(new FeedServlet()), "/feed/*");
228                 servletContextHandler.addServlet(new ServletHolder(new FeedLogServlet()), "/feedlog/*");
229                 servletContextHandler.addServlet(new ServletHolder(new PublishServlet()), "/publish/*");
230                 servletContextHandler.addServlet(new ServletHolder(new SubscribeServlet()), "/subscribe/*");
231                 servletContextHandler.addServlet(new ServletHolder(new StatisticsServlet()), "/statistics/*");
232                 servletContextHandler.addServlet(new ServletHolder(new SubLogServlet()), "/sublog/*");
233                 servletContextHandler.addServlet(new ServletHolder(new GroupServlet()), "/group/*");
234                 servletContextHandler.addServlet(new ServletHolder(new SubscriptionServlet()), "/subs/*");
235                 servletContextHandler.addServlet(new ServletHolder(new InternalServlet()), "/internal/*");
236                 servletContextHandler.addServlet(new ServletHolder(new RouteServlet()), "/internal/route/*");
237                 servletContextHandler.addServlet(new ServletHolder(new DRFeedsServlet()), "/");
238                 servletContextHandler.addFilter(new FilterHolder(new ThrottleFilter()), "/publish/*", EnumSet.of(DispatcherType.REQUEST));
239
240                 //CADI Filter activation check
241                 if (Boolean.parseBoolean(provProperties.getProperty("org.onap.dmaap.datarouter.provserver.cadi.enabled", "false"))) {
242                     //Get cadi properties
243                     Properties cadiProperties = null;
244                     try {
245                         intlogger.info("PROV0001 Prov - Loading CADI properties");
246                         cadiProperties = new Properties();
247                         Inner obj = new Main().new Inner();
248                         InputStream in = obj.getCadiProps();
249                         cadiProperties.load(in);
250                     } catch (IOException e1) {
251                         intlogger.error("PROV0001 Exception loading CADI properties", e1.getMessage());
252                     }
253                     cadiProperties.setProperty("aaf_locate_url", provProperties.getProperty("org.onap.dmaap.datarouter.provserver.cadi.aaf.url", "https://aaf-onap-test.osaaf.org:8095"));
254                     intlogger.info("PROV0001  aaf_url set to - " + cadiProperties.getProperty("aaf_url"));
255
256                     PropAccess access = new PropAccess(cadiProperties);
257                     servletContextHandler.addFilter(new FilterHolder(new DRProvCadiFilter(true, access)), "/*", EnumSet.of(DispatcherType.REQUEST));
258                 }
259
260                 ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
261                 contextHandlerCollection.addHandler(servletContextHandler);
262
263                 // Server's Handler collection
264                 handlerCollection = new HandlerCollection();
265                 handlerCollection.setHandlers(new Handler[]{contextHandlerCollection, new DefaultHandler()});
266                 handlerCollection.addHandler(requestLogHandler);
267
268                 server.setConnectors(new Connector[]{httpServerConnector, httpsServerConnector});
269             }
270         }
271         server.setHandler(handlerCollection);
272
273         // Daemon to clean up the log directory on a daily basis
274         Timer rolex = new Timer();
275         rolex.scheduleAtFixedRate(new PurgeLogDirTask(), 0, 86400000L);    // run once per day
276
277         // Start LogfileLoader
278         LogfileLoader.getLoader();
279
280         try {
281             server.start();
282             intlogger.info("Prov Server started-" + server.getState());
283         } catch (Exception e) {
284             intlogger.info("Jetty failed to start. Reporting will we unavailable", e.getMessage());
285         }
286         server.join();
287         intlogger.info("PROV0001 **** AT&T Data Router Provisioning Server halted.");
288     }
289
290     private static boolean checkDatabase() {
291         DB db = new DB();
292         return db.runRetroFits();
293     }
294
295     /**
296      * Stop the Jetty server.
297      */
298     static void shutdown() {
299         new Thread(() -> {
300             try {
301                 server.stop();
302                 Thread.sleep(5000L);
303                 System.exit(0);
304             } catch (Exception e) {
305                 intlogger.error("Exception in Main.shutdown() method " + e.getMessage());
306             }
307         });
308     }
309 }