Merge "Fix LogServlet Vulnerabilities"
[dmaap/datarouter.git] / datarouter-prov / src / main / java / org / onap / dmaap / datarouter / provisioning / BaseServlet.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 import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
28
29 import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS;
30 import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME;
31
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.net.InetAddress;
35 import java.net.UnknownHostException;
36 import java.security.cert.X509Certificate;
37 import java.sql.Connection;
38 import java.sql.SQLException;
39 import java.util.HashMap;
40 import java.util.HashSet;
41 import java.util.Map;
42 import java.util.Set;
43 import java.util.List;
44 import java.util.ArrayList;
45
46 import javax.servlet.ServletConfig;
47 import javax.servlet.ServletException;
48 import javax.servlet.http.HttpServlet;
49 import javax.servlet.http.HttpServletRequest;
50
51 import org.apache.log4j.Logger;
52 import org.json.JSONObject;
53 import org.json.JSONTokener;
54 import org.onap.dmaap.datarouter.authz.Authorizer;
55 import org.onap.dmaap.datarouter.authz.impl.ProvAuthorizer;
56 import org.onap.dmaap.datarouter.authz.impl.ProvDataProvider;
57 import org.onap.dmaap.datarouter.provisioning.beans.Deleteable;
58 import org.onap.dmaap.datarouter.provisioning.beans.Feed;
59 import org.onap.dmaap.datarouter.provisioning.beans.Group;
60 import org.onap.dmaap.datarouter.provisioning.beans.Insertable;
61 import org.onap.dmaap.datarouter.provisioning.beans.NodeClass;
62 import org.onap.dmaap.datarouter.provisioning.beans.Parameters;
63 import org.onap.dmaap.datarouter.provisioning.beans.Subscription;
64 import org.onap.dmaap.datarouter.provisioning.beans.Updateable;
65 import org.onap.dmaap.datarouter.provisioning.utils.DB;
66 import org.onap.dmaap.datarouter.provisioning.utils.ThrottleFilter;
67 import org.json.JSONException;
68 import org.slf4j.MDC;
69
70 import java.util.Properties;
71 import java.util.regex.Pattern;
72 import javax.mail.Message;
73 import javax.mail.MessagingException;
74 import javax.mail.Multipart;
75 import javax.mail.Session;
76 import javax.mail.Transport;
77 import javax.mail.internet.AddressException;
78 import javax.mail.internet.InternetAddress;
79 import javax.mail.internet.MimeBodyPart;
80 import javax.mail.internet.MimeMessage;
81 import javax.mail.internet.MimeMultipart;
82
83 /**
84  * This is the base class for all Servlets in the provisioning code. It provides standard constants and some common
85  * methods.
86  *
87  * @author Robert Eby
88  * @version $Id: BaseServlet.java,v 1.16 2014/03/12 19:45:40 eby Exp $
89  */
90 @SuppressWarnings("serial")
91 public class BaseServlet extends HttpServlet implements ProvDataProvider {
92
93     public static final String BEHALF_HEADER = "X-ATT-DR-ON-BEHALF-OF";
94     static final String FEED_BASECONTENT_TYPE = "application/vnd.att-dr.feed";
95     public static final String FEED_CONTENT_TYPE = "application/vnd.att-dr.feed; version=2.0";
96     public static final String FEEDFULL_CONTENT_TYPE = "application/vnd.att-dr.feed-full; version=2.0";
97     public static final String FEEDLIST_CONTENT_TYPE = "application/vnd.att-dr.feed-list; version=1.0";
98     static final String SUB_BASECONTENT_TYPE = "application/vnd.att-dr.subscription";
99     public static final String SUB_CONTENT_TYPE = "application/vnd.att-dr.subscription; version=2.0";
100     public static final String SUBFULL_CONTENT_TYPE = "application/vnd.att-dr.subscription-full; version=2.0";
101     static final String SUBLIST_CONTENT_TYPE = "application/vnd.att-dr.subscription-list; version=1.0";
102
103
104     //Adding groups functionality, ...1610
105     static final String GROUP_BASECONTENT_TYPE = "application/vnd.att-dr.group";
106     public static final String GROUP_CONTENT_TYPE = "application/vnd.att-dr.group; version=2.0";
107     static final String GROUPFULL_CONTENT_TYPE = "application/vnd.att-dr.group-full; version=2.0";
108     public static final String GROUPLIST_CONTENT_TYPE = "application/vnd.att-dr.fegrouped-list; version=1.0";
109
110
111     public static final String LOGLIST_CONTENT_TYPE = "application/vnd.att-dr.log-list; version=1.0";
112     public static final String PROVFULL_CONTENT_TYPE1 = "application/vnd.att-dr.provfeed-full; version=1.0";
113     public static final String PROVFULL_CONTENT_TYPE2 = "application/vnd.att-dr.provfeed-full; version=2.0";
114     public static final String CERT_ATTRIBUTE = "javax.servlet.request.X509Certificate";
115
116     static final String DB_PROBLEM_MSG = "There has been a problem with the DB.  It is suggested you try the operation again.";
117
118     private static final int DEFAULT_MAX_FEEDS = 10000;
119     private static final int DEFAULT_MAX_SUBS = 100000;
120     private static final int DEFAULT_POKETIMER1 = 5;
121     private static final int DEFAULT_POKETIMER2 = 30;
122     private static final String DEFAULT_DOMAIN = "onap";
123     private static final String DEFAULT_PROVSRVR_NAME = "dmaap-dr-prov";
124     private static final String STATIC_ROUTING_NODES = ""; //Adding new param for static Routing - Rally:US664862-1610
125
126     /**
127      * A boolean to trigger one time "provisioning changed" event on startup
128      */
129     private static boolean startmsgFlag = true;
130     /**
131      * This POD should require SSL connections from clients; pulled from the DB (PROV_REQUIRE_SECURE)
132      */
133     private static boolean requireSecure = true;
134     /**
135      * This POD should require signed, recognized certificates from clients; pulled from the DB (PROV_REQUIRE_CERT)
136      */
137     private static boolean requireCert = true;
138     /**
139      * The set of authorized addresses and networks; pulled from the DB (PROV_AUTH_ADDRESSES)
140      */
141     private static Set<String> authorizedAddressesAndNetworks = new HashSet<>();
142     /**
143      * The set of authorized names; pulled from the DB (PROV_AUTH_SUBJECTS)
144      */
145     private static Set<String> authorizedNames = new HashSet<>();
146     /**
147      * The FQDN of the initially "active" provisioning server in this Data Router ecosystem
148      */
149     private static String initialActivePod;
150     /**
151      * The FQDN of the initially "standby" provisioning server in this Data Router ecosystem
152      */
153     private static String initialStandbyPod;
154     /**
155      * The FQDN of this provisioning server in this Data Router ecosystem
156      */
157     private static String thisPod;
158     /**
159      * "Timer 1" - used to determine when to notify nodes of provisioning changes
160      */
161     private static long pokeTimer1;
162     /**
163      * "Timer 2" - used to determine when to notify nodes of provisioning changes
164      */
165     private static long pokeTimer2;
166     /**
167      * Array of nodes names and/or FQDNs
168      */
169     private static String[] nodes = new String[0];
170     /**
171      * Array of node IP addresses
172      */
173     private static InetAddress[] nodeAddresses = new InetAddress[0];
174     /**
175      * Array of POD IP addresses
176      */
177     private static InetAddress[] podAddresses = new InetAddress[0];
178     /**
179      * The maximum number of feeds allowed; pulled from the DB (PROV_MAXFEED_COUNT)
180      */
181     static int maxFeeds = 0;
182     /**
183      * The maximum number of subscriptions allowed; pulled from the DB (PROV_MAXSUB_COUNT)
184      */
185     static int maxSubs = 0;
186     /**
187      * The current number of feeds in the system
188      */
189     static int activeFeeds = 0;
190     /**
191      * The current number of subscriptions in the system
192      */
193     static int activeSubs = 0;
194     /**
195      * The domain used to generate a FQDN from the "bare" node names
196      */
197     private static String provDomain = "web.att.com";
198     /**
199      * The standard FQDN of the provisioning server in this Data Router ecosystem
200      */
201     private static String provName = "feeds-drtr.web.att.com";
202
203     /**
204      * The standard FQDN of the ACTIVE provisioning server in this Data Router ecosystem
205      */
206     private static String activeProvName = "feeds-drtr.web.att.com";
207
208     private static String staticRoutingNodes = STATIC_ROUTING_NODES; //Adding new param for static Routing - Rally:US664862-1610
209
210     /**
211      * This logger is used to log provisioning events
212      */
213     protected static Logger eventlogger;
214     /**
215      * This logger is used to log internal events (errors, etc.)
216      */
217     protected static Logger intlogger;
218     /**
219      * Authorizer - interface to the Policy Engine
220      */
221     protected static Authorizer authz;
222     /**
223      * The Synchronizer used to sync active DB to standby one
224      */
225     private static SynchronizerTask synctask = null;
226
227     //Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.
228     private InetAddress thishost;
229     private InetAddress loopback;
230     private static Boolean mailSendFlag = false;
231
232     private static final String MAILCONFIG_FILE = "mail.properties";
233     private static Properties mailprops;
234
235     //DMAAP-597 (Tech Dept) REST request source IP auth relaxation to accommodate OOM kubernetes deploy
236     private static String isAddressAuthEnabled = (new DB()).getProperties()
237         .getProperty("org.onap.dmaap.datarouter.provserver.isaddressauthenabled", "false");
238
239     /**
240      * Initialize data common to all the provisioning server servlets.
241      */
242     protected BaseServlet() {
243         if (eventlogger == null) {
244             eventlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.events");
245         }
246         if (intlogger == null) {
247             intlogger = Logger.getLogger("org.onap.dmaap.datarouter.provisioning.internal");
248         }
249         if (authz == null) {
250             authz = new ProvAuthorizer(this);
251         }
252         if (startmsgFlag) {
253             startmsgFlag = false;
254             provisioningParametersChanged();
255         }
256         if (synctask == null) {
257             synctask = SynchronizerTask.getSynchronizer();
258         }
259         String name = this.getClass().getName();
260         intlogger.info("PROV0002 Servlet " + name + " started.");
261     }
262
263     @Override
264     public void init(ServletConfig config) throws ServletException {
265         super.init(config);
266         try {
267             thishost = InetAddress.getLocalHost();
268             loopback = InetAddress.getLoopbackAddress();
269             //checkHttpsRelaxation(); //Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.
270         } catch (UnknownHostException e) {
271             // ignore
272         }
273     }
274
275     int getIdFromPath(HttpServletRequest req) {
276         String path = req.getPathInfo();
277         if (path == null || path.length() < 2) {
278             return -1;
279         }
280         try {
281             return Integer.parseInt(path.substring(1));
282         } catch (NumberFormatException e) {
283             return -1;
284         }
285     }
286
287     /**
288      * Read the request's input stream and return a JSONObject from it
289      *
290      * @param req the HTTP request
291      * @return the JSONObject, or null if the stream cannot be parsed
292      */
293     JSONObject getJSONfromInput(HttpServletRequest req) {
294         JSONObject jo = null;
295         try {
296             jo = new JSONObject(new JSONTokener(req.getInputStream()));
297             if (intlogger.isDebugEnabled()) {
298                 intlogger.debug("JSON: " + jo.toString());
299             }
300         } catch (Exception e) {
301             intlogger.info("Error reading JSON: " + e);
302         }
303         return jo;
304     }
305
306     /**
307      * Check if the remote host is authorized to perform provisioning. Is the request secure? Is it coming from an
308      * authorized IP address or network (configured via PROV_AUTH_ADDRESSES)? Does it have a valid client certificate
309      * (configured via PROV_AUTH_SUBJECTS)?
310      *
311      * @param request the request
312      * @return an error string, or null if all is OK
313      */
314     String isAuthorizedForProvisioning(HttpServletRequest request) {
315         if (!Boolean.parseBoolean(isAddressAuthEnabled)) {
316             return null;
317         }
318         // Is the request https?
319         if (requireSecure && !request.isSecure()) {
320             return "Request must be made over an HTTPS connection.";
321         }
322
323         // Is remote IP authorized?
324         String remote = request.getRemoteAddr();
325         try {
326             boolean found = false;
327             InetAddress ip = InetAddress.getByName(remote);
328             for (String addrnet : authorizedAddressesAndNetworks) {
329                 found |= addressMatchesNetwork(ip, addrnet);
330             }
331             if (!found) {
332                 return "Unauthorized address: " + remote;
333             }
334         } catch (UnknownHostException e) {
335             return "Unauthorized address: " + remote;
336         }
337
338         // Does remote have a valid certificate?
339         if (requireCert) {
340             X509Certificate certs[] = (X509Certificate[]) request.getAttribute(CERT_ATTRIBUTE);
341             if (certs == null || certs.length == 0) {
342                 return "Client certificate is missing.";
343             }
344             // cert[0] is the client cert
345             // see http://www.proto.research.att.com/java/java7/api/javax/net/ssl/SSLSession.html#getPeerCertificates()
346             String name = certs[0].getSubjectX500Principal().getName();
347             if (!authorizedNames.contains(name)) {
348                 return "No authorized certificate found.";
349             }
350         }
351
352         // No problems!
353         return null;
354     }
355
356     /**
357      * Check if the remote IP address is authorized to see the /internal URL tree.
358      *
359      * @param request the HTTP request
360      * @return true iff authorized
361      */
362     boolean isAuthorizedForInternal(HttpServletRequest request) {
363
364         try {
365             if (!Boolean.parseBoolean(isAddressAuthEnabled)) {
366                 return true;
367             }
368             InetAddress ip = InetAddress.getByName(request.getRemoteAddr());
369             for (InetAddress node : getNodeAddresses()) {
370                 if (node != null && ip.equals(node)) {
371                     return true;
372                 }
373             }
374             for (InetAddress pod : getPodAddresses()) {
375                 if (pod != null && ip.equals(pod)) {
376                     return true;
377                 }
378             }
379             if (thishost != null && ip.equals(thishost)) {
380                 return true;
381             }
382             if (loopback != null && ip.equals(loopback)) {
383                 return true;
384             }
385         } catch (UnknownHostException e) {
386             // ignore
387         }
388         return false;
389     }
390
391     /**
392      * Check if an IP address matches a network address.
393      *
394      * @param ip the IP address
395      * @param s the network address; a bare IP address may be matched also
396      * @return true if they intersect
397      */
398     private static boolean addressMatchesNetwork(InetAddress ip, String s) {
399         int mlen = -1;
400         int n = s.indexOf("/");
401         if (n >= 0) {
402             mlen = Integer.parseInt(s.substring(n + 1));
403             s = s.substring(0, n);
404         }
405         try {
406             InetAddress i2 = InetAddress.getByName(s);
407             byte[] b1 = ip.getAddress();
408             byte[] b2 = i2.getAddress();
409             if (b1.length != b2.length) {
410                 return false;
411             }
412             if (mlen > 0) {
413                 byte[] masks = {
414                     (byte) 0x00, (byte) 0x80, (byte) 0xC0, (byte) 0xE0,
415                     (byte) 0xF0, (byte) 0xF8, (byte) 0xFC, (byte) 0xFE
416                 };
417                 byte mask = masks[mlen % 8];
418                 for (n = mlen / 8; n < b1.length; n++) {
419                     b1[n] &= mask;
420                     b2[n] &= mask;
421                     mask = 0;
422                 }
423             }
424             for (n = 0; n < b1.length; n++) {
425                 if (b1[n] != b2[n]) {
426                     return false;
427                 }
428             }
429         } catch (UnknownHostException e) {
430             return false;
431         }
432         return true;
433     }
434
435     /**
436      * Something has changed in the provisioning data. Start the timers that will cause the pre-packaged JSON string to
437      * be regenerated, and cause nodes and the other provisioning server to be notified.
438      */
439     public static void provisioningDataChanged() {
440         long now = System.currentTimeMillis();
441         Poker p = Poker.getPoker();
442         p.setTimers(now + (pokeTimer1 * 1000L), now + (pokeTimer2 * 1000L));
443     }
444
445     /**
446      * Something in the parameters has changed, reload all parameters from the DB.
447      */
448     public static void provisioningParametersChanged() {
449         Map<String, String> map = Parameters.getParameters();
450         requireSecure = getBoolean(map, Parameters.PROV_REQUIRE_SECURE);
451         requireCert = getBoolean(map, Parameters.PROV_REQUIRE_CERT);
452         authorizedAddressesAndNetworks = getSet(map, Parameters.PROV_AUTH_ADDRESSES);
453         authorizedNames = getSet(map, Parameters.PROV_AUTH_SUBJECTS);
454         nodes = getSet(map, Parameters.NODES).toArray(new String[0]);
455         maxFeeds = getInt(map, Parameters.PROV_MAXFEED_COUNT, DEFAULT_MAX_FEEDS);
456         maxSubs = getInt(map, Parameters.PROV_MAXSUB_COUNT, DEFAULT_MAX_SUBS);
457         pokeTimer1 = getInt(map, Parameters.PROV_POKETIMER1, DEFAULT_POKETIMER1);
458         pokeTimer2 = getInt(map, Parameters.PROV_POKETIMER2, DEFAULT_POKETIMER2);
459         provDomain = getString(map, Parameters.PROV_DOMAIN, DEFAULT_DOMAIN);
460         provName = getString(map, Parameters.PROV_NAME, DEFAULT_PROVSRVR_NAME);
461         activeProvName = getString(map, Parameters.PROV_ACTIVE_NAME, provName);
462         staticRoutingNodes = getString(map, Parameters.STATIC_ROUTING_NODES,
463             ""); //Adding new param for static Routing - Rally:US664862-1610
464         initialActivePod = getString(map, Parameters.ACTIVE_POD, "");
465         initialStandbyPod = getString(map, Parameters.STANDBY_POD, "");
466         staticRoutingNodes = getString(map, Parameters.STATIC_ROUTING_NODES,
467             ""); //Adding new param for static Routing - Rally:US664862-1610
468         activeFeeds = Feed.countActiveFeeds();
469         activeSubs = Subscription.countActiveSubscriptions();
470         try {
471             thisPod = InetAddress.getLocalHost().getHostName();
472         } catch (UnknownHostException e) {
473             thisPod = "";
474             intlogger.warn("PROV0014 Cannot determine the name of this provisioning server.");
475         }
476
477         // Normalize the nodes, and fill in nodeAddresses
478         InetAddress[] na = new InetAddress[nodes.length];
479         for (int i = 0; i < nodes.length; i++) {
480             try {
481                 na[i] = InetAddress.getByName(nodes[i]);
482                 intlogger.debug("PROV0003 DNS lookup: " + nodes[i] + " => " + na[i].toString());
483             } catch (UnknownHostException e) {
484                 na[i] = null;
485                 intlogger.warn("PROV0004 Cannot lookup " + nodes[i] + ": " + e);
486             }
487         }
488
489         //Reset Nodes arr after - removing static routing Nodes, Rally Userstory - US664862 .
490         List<String> filterNodes = new ArrayList<>();
491         for (String node : nodes) {
492             if (!staticRoutingNodes.contains(node)) {
493                 filterNodes.add(node);
494             }
495         }
496         nodes = filterNodes.toArray(new String[filterNodes.size()]);
497
498         nodeAddresses = na;
499         NodeClass.setNodes(nodes);        // update NODES table
500
501         // Normalize the PODs, and fill in podAddresses
502         String[] pods = getPods();
503         na = new InetAddress[pods.length];
504         for (int i = 0; i < pods.length; i++) {
505             try {
506                 na[i] = InetAddress.getByName(pods[i]);
507                 intlogger.debug("PROV0003 DNS lookup: " + pods[i] + " => " + na[i].toString());
508             } catch (UnknownHostException e) {
509                 na[i] = null;
510                 intlogger.warn("PROV0004 Cannot lookup " + pods[i] + ": " + e);
511             }
512         }
513         podAddresses = na;
514
515         // Update ThrottleFilter
516         ThrottleFilter.configure();
517
518         // Check if we are active or standby POD
519         if (!isInitialActivePOD() && !isInitialStandbyPOD()) {
520             intlogger.warn("PROV0015 This machine is neither the active nor the standby POD.");
521         }
522     }
523
524
525     /**
526      * Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047. Load mail properties.
527      *
528      * @author vs215k
529      **/
530     private void loadMailProperties() {
531         if (mailprops == null) {
532             mailprops = new Properties();
533             InputStream inStream = getClass().getClassLoader().getResourceAsStream(MAILCONFIG_FILE);
534             try {
535                 mailprops.load(inStream);
536             } catch (IOException e) {
537                 intlogger.fatal("PROV9003 Opening properties: " + e.getMessage());
538                 System.exit(1);
539             } finally {
540                 try {
541                     inStream.close();
542                 } catch (IOException e) {
543                 }
544             }
545         }
546     }
547
548     /**
549      * Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047. Check if HTTPS Relexaction is enabled
550      *
551      * @author vs215k
552      **/
553     private void checkHttpsRelaxation() {
554         if (!mailSendFlag) {
555             Properties p = (new DB()).getProperties();
556             intlogger.info("HTTPS relaxation: " + p.get("org.onap.dmaap.datarouter.provserver.https.relaxation"));
557
558             if (p.get("org.onap.dmaap.datarouter.provserver.https.relaxation").equals("true")) {
559                 try {
560                     notifyPSTeam(p.get("org.onap.dmaap.datarouter.provserver.https.relax.notify").toString());
561                 } catch (Exception e) {
562                     intlogger.warn("Exception: " + e.getMessage());
563                 }
564             }
565             mailSendFlag = true;
566         }
567     }
568
569     /**
570      * Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.
571      *
572      * @param email - list of email ids to notify if HTTP relexcation is enabled.
573      * @author vs215k
574      **/
575     private void notifyPSTeam(String email) throws Exception {
576         loadMailProperties(); //Load HTTPS Relex mail properties.
577         String[] emails = email.split(Pattern.quote("|"));
578
579         Properties mailproperties = new Properties();
580         mailproperties.put("mail.smtp.host", mailprops.get("com.att.dmaap.datarouter.mail.server"));
581         mailproperties.put("mail.transport.protocol", mailprops.get("com.att.dmaap.datarouter.mail.protocol"));
582
583         Session session = Session.getDefaultInstance(mailproperties, null);
584         Multipart mp = new MimeMultipart();
585         MimeBodyPart htmlPart = new MimeBodyPart();
586
587         try {
588
589             Message msg = new MimeMessage(session);
590             msg.setFrom(new InternetAddress(mailprops.get("com.att.dmaap.datarouter.mail.from").toString()));
591
592             InternetAddress[] addressTo = new InternetAddress[emails.length];
593             for (int x = 0; x < emails.length; x++) {
594                 addressTo[x] = new InternetAddress(emails[x]);
595             }
596
597             msg.addRecipients(Message.RecipientType.TO, addressTo);
598             msg.setSubject(mailprops.get("com.att.dmaap.datarouter.mail.subject").toString());
599             htmlPart.setContent(mailprops.get("com.att.dmaap.datarouter.mail.body").toString()
600                 .replace("[SERVER]", InetAddress.getLocalHost().getHostName()), "text/html");
601             mp.addBodyPart(htmlPart);
602             msg.setContent(mp);
603
604             System.out.println(mailprops.get("com.att.dmaap.datarouter.mail.body").toString()
605                 .replace("[SERVER]", InetAddress.getLocalHost().getHostName()));
606
607             Transport.send(msg);
608             intlogger.info("HTTPS relaxation mail is sent to - : " + email);
609
610         } catch (AddressException e) {
611             intlogger.error("Invalid email address, unable to send https relaxation mail to - : " + email);
612         } catch (MessagingException e) {
613             intlogger.error("Invalid email address, unable to send https relaxation mail to - : " + email);
614         }
615     }
616
617     public static String getProvName() {
618         return provName;
619     }
620
621     public static String getActiveProvName() {
622         return activeProvName;
623     }
624
625     /**
626      * Get an array of all node names in the DR network.
627      *
628      * @return an array of Strings
629      */
630     public static String[] getNodes() {
631         return nodes;
632     }
633
634     /**
635      * Get an array of all node InetAddresses in the DR network.
636      *
637      * @return an array of InetAddresses
638      */
639     public static InetAddress[] getNodeAddresses() {
640         return nodeAddresses;
641     }
642
643     /**
644      * Get an array of all POD names in the DR network.
645      *
646      * @return an array of Strings
647      */
648     public static String[] getPods() {
649         return new String[]{initialActivePod, initialStandbyPod};
650     }
651
652     /**
653      * Get an array of all POD InetAddresses in the DR network.
654      *
655      * @return an array of InetAddresses
656      */
657     private static InetAddress[] getPodAddresses() {
658         return podAddresses;
659     }
660
661     /**
662      * Gets the FQDN of the initially ACTIVE provisioning server (POD). Note: this used to be called isActivePOD(),
663      * however, that is a misnomer, as the active status could shift to the standby POD without these parameters
664      * changing.  Hence, the function names have been changed to more accurately reflect their purpose.
665      *
666      * @return the FQDN
667      */
668     public static boolean isInitialActivePOD() {
669         return thisPod.equals(initialActivePod);
670     }
671
672     /**
673      * Gets the FQDN of the initially STANDBY provisioning server (POD). Note: this used to be called isStandbyPOD(),
674      * however, that is a misnomer, as the standby status could shift to the active POD without these parameters
675      * changing.  Hence, the function names have been changed to more accurately reflect their purpose.
676      *
677      * @return the FQDN
678      */
679     public static boolean isInitialStandbyPOD() {
680         return thisPod.equals(initialStandbyPod);
681     }
682
683     /**
684      * INSERT an {@link Insertable} bean into the database.
685      *
686      * @param bean the bean representing a row to insert
687      * @return true if the INSERT was successful
688      */
689     protected boolean doInsert(Insertable bean) {
690         boolean rv;
691         DB db = new DB();
692         Connection conn = null;
693         try {
694             conn = db.getConnection();
695             rv = bean.doInsert(conn);
696         } catch (SQLException e) {
697             rv = false;
698             intlogger.warn("PROV0005 doInsert: " + e.getMessage());
699         } finally {
700             if (conn != null) {
701                 db.release(conn);
702             }
703         }
704         return rv;
705     }
706
707     /**
708      * UPDATE an {@link Updateable} bean in the database.
709      *
710      * @param bean the bean representing a row to update
711      * @return true if the UPDATE was successful
712      */
713     protected boolean doUpdate(Updateable bean) {
714         boolean rv;
715         DB db = new DB();
716         Connection conn = null;
717         try {
718             conn = db.getConnection();
719             rv = bean.doUpdate(conn);
720         } catch (SQLException e) {
721             rv = false;
722             intlogger.warn("PROV0006 doUpdate: " + e.getMessage());
723         } finally {
724             if (conn != null) {
725                 db.release(conn);
726             }
727         }
728         return rv;
729     }
730
731     /**
732      * DELETE an {@link Deleteable} bean from the database.
733      *
734      * @param bean the bean representing a row to delete
735      * @return true if the DELETE was successful
736      */
737     protected boolean doDelete(Deleteable bean) {
738         boolean rv;
739         DB db = new DB();
740         Connection conn = null;
741         try {
742             conn = db.getConnection();
743             rv = bean.doDelete(conn);
744         } catch (SQLException e) {
745             rv = false;
746             intlogger.warn("PROV0007 doDelete: " + e.getMessage());
747         } finally {
748             if (conn != null) {
749                 db.release(conn);
750             }
751         }
752         return rv;
753     }
754
755     private static boolean getBoolean(Map<String, String> map, String name) {
756         String s = map.get(name);
757         return (s != null) && s.equalsIgnoreCase("true");
758     }
759
760     private static String getString(Map<String, String> map, String name, String dflt) {
761         String s = map.get(name);
762         return (s != null) ? s : dflt;
763     }
764
765     private static int getInt(Map<String, String> map, String name, int dflt) {
766         try {
767             String s = map.get(name);
768             return Integer.parseInt(s);
769         } catch (NumberFormatException e) {
770             return dflt;
771         }
772     }
773
774     private static Set<String> getSet(Map<String, String> map, String name) {
775         Set<String> set = new HashSet<>();
776         String s = map.get(name);
777         if (s != null) {
778             String[] pp = s.split("\\|");
779             if (pp != null) {
780                 for (String t : pp) {
781                     String t2 = t.trim();
782                     if (t2.length() > 0) {
783                         set.add(t2);
784                     }
785                 }
786             }
787         }
788         return set;
789     }
790
791     /**
792      * A class used to encapsulate a Content-type header, separating out the "version" attribute (which defaults to
793      * "1.0" if missing).
794      */
795     public class ContentHeader {
796
797         private String type = "";
798         private Map<String, String> map = new HashMap<>();
799
800         ContentHeader() {
801             this("", "1.0");
802         }
803
804         ContentHeader(String t, String v) {
805             type = t.trim();
806             map.put("version", v);
807         }
808
809         public String getType() {
810             return type;
811         }
812
813         public String getAttribute(String key) {
814             String s = map.get(key);
815             if (s == null) {
816                 s = "";
817             }
818             return s;
819         }
820     }
821
822     /**
823      * Get the ContentHeader from an HTTP request.
824      *
825      * @param req the request
826      * @return the header, encapsulated in a ContentHeader object
827      */
828     ContentHeader getContentHeader(HttpServletRequest req) {
829         ContentHeader ch = new ContentHeader();
830         String s = req.getHeader("Content-Type");
831         if (s != null) {
832             String[] pp = s.split(";");
833             ch.type = pp[0].trim();
834             for (int i = 1; i < pp.length; i++) {
835                 int ix = pp[i].indexOf('=');
836                 if (ix > 0) {
837                     String k = pp[i].substring(0, ix).trim();
838                     String v = pp[i].substring(ix + 1).trim();
839                     ch.map.put(k, v);
840                 } else {
841                     ch.map.put(pp[i].trim(), "");
842                 }
843             }
844         }
845         return ch;
846     }
847
848     // Methods for the Policy Engine classes - ProvDataProvider interface
849     @Override
850     public String getFeedOwner(String feedId) {
851         try {
852             int n = Integer.parseInt(feedId);
853             Feed f = Feed.getFeedById(n);
854             if (f != null) {
855                 return f.getPublisher();
856             }
857         } catch (NumberFormatException e) {
858             // ignore
859         }
860         return null;
861     }
862
863     @Override
864     public String getFeedClassification(String feedId) {
865         try {
866             int n = Integer.parseInt(feedId);
867             Feed f = Feed.getFeedById(n);
868             if (f != null) {
869                 return f.getAuthorization().getClassification();
870             }
871         } catch (NumberFormatException e) {
872             // ignore
873         }
874         return null;
875     }
876
877     @Override
878     public String getSubscriptionOwner(String subId) {
879         try {
880             int n = Integer.parseInt(subId);
881             Subscription s = Subscription.getSubscriptionById(n);
882             if (s != null) {
883                 return s.getSubscriber();
884             }
885         } catch (NumberFormatException e) {
886             // ignore
887         }
888         return null;
889     }
890
891     /*
892      * @Method - isUserMemberOfGroup - Rally:US708115
893      * @Params - group object and user to check if exists in given group
894      * @return - boolean value /true/false
895      */
896     private boolean isUserMemberOfGroup(Group group, String user) {
897
898         String groupDetails = group.getMembers().replace("]", "").replace("[", "");
899         String[] s = groupDetails.split("},");
900
901         for (String value : s) {
902             JSONObject jsonObj;
903             try {
904                 jsonObj = new JSONObject(value + "}");
905                 if (jsonObj.get("id").equals(user)) {
906                     return true;
907                 }
908             } catch (JSONException e) {
909                 intlogger.error("JSONException: " + e.getMessage());
910             }
911         }
912         return false;
913
914     }
915
916     /*
917      * @Method - getGroupByFeedGroupId- Rally:US708115
918      * @Params - User to check in group and feedid which is assigned the group.
919      * @return - string value grupid/null
920      */
921     @Override
922     public String getGroupByFeedGroupId(String owner, String feedId) {
923         try {
924             int n = Integer.parseInt(feedId);
925             Feed f = Feed.getFeedById(n);
926             if (f != null) {
927                 int groupid = f.getGroupid();
928                 if (groupid > 0) {
929                     Group group = Group.getGroupById(groupid);
930                     assert group != null;
931                     if (isUserMemberOfGroup(group, owner)) {
932                         return group.getAuthid();
933                     }
934                 }
935             }
936         } catch (NumberFormatException e) {
937             // ignore
938         }
939         return null;
940     }
941
942     /*
943      * @Method - getGroupBySubGroupId - Rally:US708115
944      * @Params - User to check in group and subid which is assigned the group.
945      * @return - string value grupid/null
946      */
947     @Override
948     public String getGroupBySubGroupId(String owner, String subId) {
949         try {
950             int n = Integer.parseInt(subId);
951             Subscription s = Subscription.getSubscriptionById(n);
952             if (s != null) {
953                 int groupid = s.getGroupid();
954                 if (groupid > 0) {
955                     Group group = Group.getGroupById(groupid);
956                     assert group != null;
957                     if (isUserMemberOfGroup(group, owner)) {
958                         return group.getAuthid();
959                     }
960                 }
961             }
962         } catch (NumberFormatException e) {
963             // ignore
964         }
965         return null;
966     }
967
968     /*
969      * @Method - setIpAndFqdnForEelf - Rally:US664892
970      * @Params - method, prints method name in EELF log.
971      */
972     void setIpAndFqdnForEelf(String method) {
973         MDC.clear();
974         MDC.put(MDC_SERVICE_NAME, method);
975         try {
976             MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName());
977             MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
978         } catch (Exception e) {
979             intlogger.error("Exception: " + e.getMessage());
980         }
981
982     }
983 }