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