1 /*******************************************************************************
2 * ============LICENSE_START==================================================
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
11 * * http://www.apache.org/licenses/LICENSE-2.0
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====================================================
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 ******************************************************************************/
25 package org.onap.dmaap.datarouter.provisioning;
27 import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN;
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;
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;
43 import javax.servlet.ServletConfig;
44 import javax.servlet.ServletException;
45 import javax.servlet.http.HttpServlet;
46 import javax.servlet.http.HttpServletRequest;
48 import com.att.eelf.configuration.EELFLogger;
49 import com.att.eelf.configuration.EELFManager;
50 import org.apache.commons.lang3.StringUtils;
51 import org.json.JSONArray;
52 import org.json.JSONException;
53 import org.json.JSONObject;
54 import org.json.JSONTokener;
55 import org.onap.dmaap.datarouter.authz.Authorizer;
56 import org.onap.dmaap.datarouter.authz.impl.ProvAuthorizer;
57 import org.onap.dmaap.datarouter.authz.impl.ProvDataProvider;
58 import org.onap.dmaap.datarouter.provisioning.beans.*;
59 import org.onap.dmaap.datarouter.provisioning.utils.DB;
60 import org.onap.dmaap.datarouter.provisioning.utils.PasswordProcessor;
61 import org.onap.dmaap.datarouter.provisioning.utils.ThrottleFilter;
65 import javax.mail.internet.InternetAddress;
66 import javax.mail.internet.MimeBodyPart;
67 import javax.mail.internet.MimeMessage;
68 import javax.mail.internet.MimeMultipart;
69 import java.security.GeneralSecurityException;
71 import java.util.regex.Pattern;
75 * This is the base class for all Servlets in the provisioning code. It provides standard constants and some common
79 * @version $Id: BaseServlet.java,v 1.16 2014/03/12 19:45:40 eby Exp $
81 @SuppressWarnings("serial")
82 public class BaseServlet extends HttpServlet implements ProvDataProvider {
84 public static final String BEHALF_HEADER = "X-DMAAP-DR-ON-BEHALF-OF";
86 public static final String EXCLUDE_AAF_HEADER = "X-EXCLUDE-AAF";
88 private static final String AAF_CADI_FEED_TYPE = "org.onap.dmaap.datarouter.provserver.aaf.feed.type";
89 private static final String AAF_CADI_SUB_TYPE = "org.onap.dmaap.datarouter.provserver.aaf.sub.type";
90 private static final String AAF_INSTANCE = "org.onap.dmaap.datarouter.provserver.aaf.instance";
91 private static final String AAF_CADI_FEED = "org.onap.dmaap-dr.feed";
92 private static final String AAF_CADI_SUB = "org.onap.dmaap-dr.sub";
94 static final String CREATE_PERMISSION = "create";
95 static final String EDIT_PERMISSION = "edit";
96 static final String DELETE_PERMISSION = "delete";
97 static final String PUBLISH_PERMISSION = "publish";
98 static final String SUSPEND_PERMISSION = "suspend";
99 static final String RESTORE_PERMISSION = "restore";
100 static final String SUBSCRIBE_PERMISSION = "subscribe";
101 static final String APPROVE_SUB_PERMISSION = "approveSub";
103 static final String FEED_BASECONTENT_TYPE = "application/vnd.dmaap-dr.feed";
104 public static final String FEED_CONTENT_TYPE = "application/vnd.dmaap-dr.feed; version=2.0";
105 public static final String FEEDFULL_CONTENT_TYPE = "application/vnd.dmaap-dr.feed-full; version=2.0";
106 public static final String FEEDLIST_CONTENT_TYPE = "application/vnd.dmaap-dr.feed-list; version=1.0";
107 static final String SUB_BASECONTENT_TYPE = "application/vnd.dmaap-dr.subscription";
108 public static final String SUB_CONTENT_TYPE = "application/vnd.dmaap-dr.subscription; version=2.0";
109 public static final String SUBFULL_CONTENT_TYPE = "application/vnd.dmaap-dr.subscription-full; version=2.0";
110 static final String SUBLIST_CONTENT_TYPE = "application/vnd.dmaap-dr.subscription-list; version=1.0";
113 //Adding groups functionality, ...1610
114 static final String GROUP_BASECONTENT_TYPE = "application/vnd.dmaap-dr.group";
115 static final String GROUP_CONTENT_TYPE = "application/vnd.dmaap-dr.group; version=2.0";
116 public static final String GROUPFULL_CONTENT_TYPE = "application/vnd.dmaap-dr.group-full; version=2.0";
117 public static final String GROUPLIST_CONTENT_TYPE = "application/vnd.dmaap-dr.fegrouped-list; version=1.0";
120 public static final String LOGLIST_CONTENT_TYPE = "application/vnd.dmaap-dr.log-list; version=1.0";
121 public static final String PROVFULL_CONTENT_TYPE1 = "application/vnd.dmaap-dr.provfeed-full; version=1.0";
122 public static final String PROVFULL_CONTENT_TYPE2 = "application/vnd.dmaap-dr.provfeed-full; version=2.0";
123 public static final String CERT_ATTRIBUTE = "javax.servlet.request.X509Certificate";
125 static final String DB_PROBLEM_MSG = "There has been a problem with the DB. It is suggested you try the operation again.";
127 private static final int DEFAULT_MAX_FEEDS = 10000;
128 private static final int DEFAULT_MAX_SUBS = 100000;
129 private static final int DEFAULT_POKETIMER1 = 5;
130 private static final int DEFAULT_POKETIMER2 = 30;
131 private static final String DEFAULT_DOMAIN = "onap";
132 private static final String DEFAULT_PROVSRVR_NAME = "dmaap-dr-prov";
133 private static final String STATIC_ROUTING_NODES = ""; //Adding new param for static Routing - Rally:US664862-1610
136 * A boolean to trigger one time "provisioning changed" event on startup
138 private static boolean startmsgFlag = true;
140 * This POD should require SSL connections from clients; pulled from the DB (PROV_REQUIRE_SECURE)
142 private static boolean requireSecure = true;
144 * This POD should require signed, recognized certificates from clients; pulled from the DB (PROV_REQUIRE_CERT)
146 private static boolean requireCert = true;
148 * The set of authorized addresses and networks; pulled from the DB (PROV_AUTH_ADDRESSES)
150 private static Set<String> authorizedAddressesAndNetworks = new HashSet<>();
152 * The set of authorized names; pulled from the DB (PROV_AUTH_SUBJECTS)
154 private static Set<String> authorizedNames = new HashSet<>();
156 * The FQDN of the initially "active" provisioning server in this Data Router ecosystem
158 private static String initialActivePod;
160 * The FQDN of the initially "standby" provisioning server in this Data Router ecosystem
162 private static String initialStandbyPod;
164 * The FQDN of this provisioning server in this Data Router ecosystem
166 private static String thisPod;
168 * "Timer 1" - used to determine when to notify nodes of provisioning changes
170 private static long pokeTimer1;
172 * "Timer 2" - used to determine when to notify nodes of provisioning changes
174 private static long pokeTimer2;
176 * Array of nodes names and/or FQDNs
178 private static String[] nodes = new String[0];
180 * [DATARTR-27] Poke all the DR nodes : Array of nodes names and/or FQDNs
182 private static String[] drnodes = new String[0];
184 * Array of node IP addresses
186 private static InetAddress[] nodeAddresses = new InetAddress[0];
188 * Array of POD IP addresses
190 private static InetAddress[] podAddresses = new InetAddress[0];
192 * The maximum number of feeds allowed; pulled from the DB (PROV_MAXFEED_COUNT)
194 static int maxFeeds = 0;
196 * The maximum number of subscriptions allowed; pulled from the DB (PROV_MAXSUB_COUNT)
198 static int maxSubs = 0;
200 * The current number of feeds in the system
202 static int activeFeeds = 0;
204 * The current number of subscriptions in the system
206 static int activeSubs = 0;
209 * The domain used to generate a FQDN from the "bare" node names
211 private static String provDomain = "web.att.com";
214 * The standard FQDN of the provisioning server in this Data Router ecosystem
216 private static String provName = "feeds-drtr.web.att.com";
219 * The standard FQDN of the ACTIVE provisioning server in this Data Router ecosystem
221 private static String activeProvName = "feeds-drtr.web.att.com";
223 //Adding new param for static Routing - Rally:US664862-1610
224 private static String staticRoutingNodes = STATIC_ROUTING_NODES;
227 * This logger is used to log provisioning events
229 protected static EELFLogger eventlogger;
231 * This logger is used to log internal events (errors, etc.)
233 protected static EELFLogger intlogger;
235 * Authorizer - interface to the Policy Engine
237 protected static Authorizer authz;
239 * The Synchronizer used to sync active DB to standby one
241 private static SynchronizerTask synctask = null;
243 //Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.
244 private InetAddress thishost;
245 private InetAddress loopback;
246 private static Boolean mailSendFlag = false;
248 private static final String MAILCONFIG_FILE = "mail.properties";
249 private static Properties mailprops;
251 //DMAAP-597 (Tech Dept) REST request source IP auth relaxation to accommodate OOM kubernetes deploy
252 private static String isAddressAuthEnabled = (new DB()).getProperties()
253 .getProperty("org.onap.dmaap.datarouter.provserver.isaddressauthenabled", "false");
255 static String isCadiEnabled = (new DB()).getProperties()
256 .getProperty("org.onap.dmaap.datarouter.provserver.cadi.enabled", "false");
259 * Initialize data common to all the provisioning server servlets.
261 protected BaseServlet() {
262 if(eventlogger == null) {
263 this.eventlogger = EELFManager.getInstance().getLogger("EventLog");
265 if(intlogger == null) {
266 this.intlogger = EELFManager.getInstance().getLogger("InternalLog");
269 authz = new ProvAuthorizer(this);
272 startmsgFlag = false;
273 provisioningParametersChanged();
275 if (synctask == null) {
276 synctask = SynchronizerTask.getSynchronizer();
278 String name = this.getClass().getName();
279 intlogger.info("PROV0002 Servlet " + name + " started.");
283 public void init(ServletConfig config) throws ServletException {
286 thishost = InetAddress.getLocalHost();
287 loopback = InetAddress.getLoopbackAddress();
288 //checkHttpsRelaxation(); //Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.
289 } catch (UnknownHostException e) {
290 intlogger.info("BaseServlet.init: " + e.getMessage(), e);
294 public static int getIdFromPath(HttpServletRequest req) {
295 String path = req.getPathInfo();
296 if (path == null || path.length() < 2) {
300 return Integer.parseInt(path.substring(1));
301 } catch (NumberFormatException e) {
307 * Read the request's input stream and return a JSONObject from it
309 * @param req the HTTP request
310 * @return the JSONObject, or null if the stream cannot be parsed
312 JSONObject getJSONfromInput(HttpServletRequest req) {
313 JSONObject jo = null;
315 jo = new JSONObject(new JSONTokener(req.getInputStream()));
316 if (intlogger.isDebugEnabled()) {
317 intlogger.debug("JSON: " + jo.toString());
319 } catch (Exception e) {
320 intlogger.info("Error reading JSON: " + e);
326 * This method encrypt/decrypt the key in the JSON passed by user request inside the authorisation header object in request before logging the JSON.
328 * @param jo- the JSON passed in http request.
329 * @param maskKey- the key to be masked in the JSON passed.
330 * @param action- whether to mask the key or unmask it in a JSON passed.
331 * @return the JSONObject, or null if the stream cannot be parsed.
333 public static JSONObject maskJSON(JSONObject jo, String maskKey, boolean action) {
334 if (!jo.isNull("authorization")) {
335 JSONObject j2 = jo.getJSONObject("authorization");
336 JSONArray ja = j2.getJSONArray("endpoint_ids");
337 for (int i = 0; i < ja.length(); i++) {
338 if ((!ja.getJSONObject(i).isNull(maskKey))) {
339 String password = ja.getJSONObject(i).get(maskKey).toString();
342 ja.getJSONObject(i).put(maskKey, PasswordProcessor.encrypt(password));
344 ja.getJSONObject(i).put(maskKey, PasswordProcessor.decrypt(password));
346 } catch (JSONException | GeneralSecurityException e) {
347 intlogger.info("Error reading JSON while masking: " + e);
356 * Check if the remote host is authorized to perform provisioning. Is the request secure? Is it coming from an
357 * authorized IP address or network (configured via PROV_AUTH_ADDRESSES)? Does it have a valid client certificate
358 * (configured via PROV_AUTH_SUBJECTS)?
360 * @param request the request
361 * @return an error string, or null if all is OK
363 String isAuthorizedForProvisioning(HttpServletRequest request) {
364 if (!Boolean.parseBoolean(isAddressAuthEnabled)) {
367 // Is the request https?
368 if (requireSecure && !request.isSecure()) {
369 return "Request must be made over an HTTPS connection.";
371 // Is remote IP authorized?
372 String remote = request.getRemoteAddr();
374 boolean found = false;
375 InetAddress ip = InetAddress.getByName(remote);
376 for (String addrnet : authorizedAddressesAndNetworks) {
377 found |= addressMatchesNetwork(ip, addrnet);
380 return "Unauthorized address: " + remote;
382 } catch (UnknownHostException e) {
383 intlogger.error("PROV0051 BaseServlet.isAuthorizedForProvisioning: " + e.getMessage(), e);
384 return "Unauthorized address: " + remote;
386 // Does remote have a valid certificate?
388 X509Certificate[] certs = (X509Certificate[]) request.getAttribute(CERT_ATTRIBUTE);
389 if (certs == null || certs.length == 0) {
390 return "Client certificate is missing.";
392 // cert[0] is the client cert
393 // see http://www.proto.research.att.com/java/java7/api/javax/net/ssl/SSLSession.html#getPeerCertificates()
394 String name = certs[0].getSubjectX500Principal().getName();
395 if (!authorizedNames.contains(name)) {
396 return "No authorized certificate found.";
404 * Check if the remote IP address is authorized to see the /internal URL tree.
406 * @param request the HTTP request
407 * @return true iff authorized
409 boolean isAuthorizedForInternal(HttpServletRequest request) {
411 if (!Boolean.parseBoolean(isAddressAuthEnabled)) {
414 InetAddress ip = InetAddress.getByName(request.getRemoteAddr());
415 for (InetAddress node : getNodeAddresses()) {
416 if (node != null && ip.equals(node)) {
420 for (InetAddress pod : getPodAddresses()) {
421 if (pod != null && ip.equals(pod)) {
425 if (thishost != null && ip.equals(thishost)) {
428 if (loopback != null && ip.equals(loopback)) {
431 } catch (UnknownHostException e) {
432 intlogger.error("PROV0052 BaseServlet.isAuthorizedForInternal: " + e.getMessage(), e);
438 * Check if an IP address matches a network address.
440 * @param ip the IP address
441 * @param s the network address; a bare IP address may be matched also
442 * @return true if they intersect
444 private static boolean addressMatchesNetwork(InetAddress ip, String s) {
446 int n = s.indexOf("/");
448 mlen = Integer.parseInt(s.substring(n + 1));
449 s = s.substring(0, n);
452 InetAddress i2 = InetAddress.getByName(s);
453 byte[] b1 = ip.getAddress();
454 byte[] b2 = i2.getAddress();
455 if (b1.length != b2.length) {
460 (byte) 0x00, (byte) 0x80, (byte) 0xC0, (byte) 0xE0,
461 (byte) 0xF0, (byte) 0xF8, (byte) 0xFC, (byte) 0xFE
463 byte mask = masks[mlen % 8];
464 for (n = mlen / 8; n < b1.length; n++) {
470 for (n = 0; n < b1.length; n++) {
471 if (b1[n] != b2[n]) {
475 } catch (UnknownHostException e) {
476 intlogger.error("PROV0053 BaseServlet.addressMatchesNetwork: " + e.getMessage(), e);
483 * Something has changed in the provisioning data. Start the timers that will cause the pre-packaged JSON string to
484 * be regenerated, and cause nodes and the other provisioning server to be notified.
486 static void provisioningDataChanged() {
487 long now = System.currentTimeMillis();
488 Poker p = Poker.getPoker();
489 p.setTimers(now + (pokeTimer1 * 1000L), now + (pokeTimer2 * 1000L));
493 * Something in the parameters has changed, reload all parameters from the DB.
495 static void provisioningParametersChanged() {
496 Map<String, String> map = Parameters.getParameters();
497 requireSecure = getBoolean(map, Parameters.PROV_REQUIRE_SECURE);
498 requireCert = getBoolean(map, Parameters.PROV_REQUIRE_CERT);
499 authorizedAddressesAndNetworks = getSet(map, Parameters.PROV_AUTH_ADDRESSES);
500 authorizedNames = getSet(map, Parameters.PROV_AUTH_SUBJECTS);
501 nodes = getSet(map, Parameters.NODES).toArray(new String[0]);
502 maxFeeds = getInt(map, Parameters.PROV_MAXFEED_COUNT, DEFAULT_MAX_FEEDS);
503 maxSubs = getInt(map, Parameters.PROV_MAXSUB_COUNT, DEFAULT_MAX_SUBS);
504 pokeTimer1 = getInt(map, Parameters.PROV_POKETIMER1, DEFAULT_POKETIMER1);
505 pokeTimer2 = getInt(map, Parameters.PROV_POKETIMER2, DEFAULT_POKETIMER2);
507 * The domain used to generate a FQDN from the "bare" node names
509 provDomain = getString(map, Parameters.PROV_DOMAIN, DEFAULT_DOMAIN);
510 provName = getString(map, Parameters.PROV_NAME, DEFAULT_PROVSRVR_NAME);
511 activeProvName = getString(map, Parameters.PROV_ACTIVE_NAME, provName);
512 initialActivePod = getString(map, Parameters.ACTIVE_POD, "");
513 initialStandbyPod = getString(map, Parameters.STANDBY_POD, "");
514 staticRoutingNodes = getString(map, Parameters.STATIC_ROUTING_NODES,
515 ""); //Adding new param for static Routing - Rally:US664862-1610
516 activeFeeds = Feed.countActiveFeeds();
517 activeSubs = Subscription.countActiveSubscriptions();
519 thisPod = InetAddress.getLocalHost().getHostName();
520 } catch (UnknownHostException e) {
522 intlogger.warn("PROV0014 Cannot determine the name of this provisioning server.", e);
525 // Normalize the nodes, and fill in nodeAddresses
526 InetAddress[] na = new InetAddress[nodes.length];
527 for (int i = 0; i < nodes.length; i++) {
529 na[i] = InetAddress.getByName(nodes[i]);
530 intlogger.debug("PROV0003 DNS lookup: " + nodes[i] + " => " + na[i].toString());
531 } catch (UnknownHostException e) {
533 intlogger.warn("PROV0004 Cannot lookup " + nodes[i] + ": " + e.getMessage(), e);
537 //[DATARTR-27] Poke all the DR nodes: assigning DR Nodes
538 drnodes = nodes.clone();
540 //Reset Nodes arr after - removing static routing Nodes, Rally Userstory - US664862 .
541 List<String> filterNodes = new ArrayList<>();
542 for (String node : nodes) {
543 if (!staticRoutingNodes.contains(node)) {
544 filterNodes.add(node);
547 nodes = filterNodes.toArray(new String[0]);
550 NodeClass.setNodes(nodes); // update NODES table
552 // Normalize the PODs, and fill in podAddresses
553 String[] pods = getPods();
554 na = new InetAddress[pods.length];
555 for (int i = 0; i < pods.length; i++) {
557 na[i] = InetAddress.getByName(pods[i]);
558 intlogger.debug("PROV0003 DNS lookup: " + pods[i] + " => " + na[i].toString());
559 } catch (UnknownHostException e) {
561 intlogger.warn("PROV0004 Cannot lookup " + pods[i] + ": " + e.getMessage(), e);
566 // Update ThrottleFilter
567 ThrottleFilter.configure();
569 // Check if we are active or standby POD
570 if (!isInitialActivePOD() && !isInitialStandbyPOD()) {
571 intlogger.warn("PROV0015 This machine is neither the active nor the standby POD.");
577 * Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047. Load mail properties.
581 private void loadMailProperties() {
582 if (mailprops == null) {
583 mailprops = new Properties();
584 try (InputStream inStream = getClass().getClassLoader().getResourceAsStream(MAILCONFIG_FILE)) {
585 mailprops.load(inStream);
586 } catch (IOException e) {
587 intlogger.error("PROV9003 Opening properties: " + e.getMessage(), e);
594 * Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047. Check if HTTPS Relexaction is enabled
598 private void checkHttpsRelaxation() {
600 Properties p = (new DB()).getProperties();
601 intlogger.info("HTTPS relaxation: " + p.get("org.onap.dmaap.datarouter.provserver.https.relaxation"));
603 if (p.get("org.onap.dmaap.datarouter.provserver.https.relaxation").equals("true")) {
605 notifyPSTeam(p.get("org.onap.dmaap.datarouter.provserver.https.relax.notify").toString());
606 } catch (Exception e) {
607 intlogger.warn("Exception: " + e.getMessage(), e);
615 * Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.
617 * @param email - list of email ids to notify if HTTP relexcation is enabled.
620 private void notifyPSTeam(String email) {
621 loadMailProperties(); //Load HTTPS Relex mail properties.
622 String[] emails = email.split(Pattern.quote("|"));
624 Properties mailproperties = new Properties();
625 mailproperties.put("mail.smtp.host", mailprops.get("com.att.dmaap.datarouter.mail.server"));
626 mailproperties.put("mail.transport.protocol", mailprops.get("com.att.dmaap.datarouter.mail.protocol"));
628 Session session = Session.getDefaultInstance(mailproperties, null);
629 Multipart mp = new MimeMultipart();
630 MimeBodyPart htmlPart = new MimeBodyPart();
634 Message msg = new MimeMessage(session);
635 msg.setFrom(new InternetAddress(mailprops.get("com.att.dmaap.datarouter.mail.from").toString()));
637 InternetAddress[] addressTo = new InternetAddress[emails.length];
638 for (int x = 0; x < emails.length; x++) {
639 addressTo[x] = new InternetAddress(emails[x]);
642 msg.addRecipients(Message.RecipientType.TO, addressTo);
643 msg.setSubject(mailprops.get("com.att.dmaap.datarouter.mail.subject").toString());
644 htmlPart.setContent(mailprops.get("com.att.dmaap.datarouter.mail.body").toString()
645 .replace("[SERVER]", InetAddress.getLocalHost().getHostName()), "text/html");
646 mp.addBodyPart(htmlPart);
649 System.out.println(mailprops.get("com.att.dmaap.datarouter.mail.body").toString()
650 .replace("[SERVER]", InetAddress.getLocalHost().getHostName()));
653 intlogger.info("HTTPS relaxation mail is sent to - : " + email);
655 } catch (MessagingException e) {
656 intlogger.error("Invalid email address, unable to send https relaxation mail to - : " + email, e);
657 } catch (UnknownHostException uhe) {
658 intlogger.error("UnknownHostException", uhe);
662 public static String getProvName() {
666 public static String getActiveProvName() {
667 return activeProvName;
671 * Get an array of all node names in the DR network.
673 * @return an array of Strings
675 public static String[] getNodes() {
680 * [DATARTR-27] Poke all the DR nodes
681 * Get an array of all node names in the DR network.
683 * @return an array of Strings
685 public static String[] getDRNodes() {
690 * Get an array of all node InetAddresses in the DR network.
692 * @return an array of InetAddresses
694 public static InetAddress[] getNodeAddresses() {
695 return nodeAddresses;
699 * Get an array of all POD names in the DR network.
701 * @return an array of Strings
703 public static String[] getPods() {
704 return new String[]{initialActivePod, initialStandbyPod};
708 * Get an array of all POD InetAddresses in the DR network.
710 * @return an array of InetAddresses
712 private static InetAddress[] getPodAddresses() {
717 * Gets the FQDN of the initially ACTIVE provisioning server (POD). Note: this used to be called isActivePOD(),
718 * however, that is a misnomer, as the active status could shift to the standby POD without these parameters
719 * changing. Hence, the function names have been changed to more accurately reflect their purpose.
723 public static boolean isInitialActivePOD() {
724 return thisPod.equals(initialActivePod);
728 * Gets the FQDN of the initially STANDBY provisioning server (POD). Note: this used to be called isStandbyPOD(),
729 * however, that is a misnomer, as the standby status could shift to the active POD without these parameters
730 * changing. Hence, the function names have been changed to more accurately reflect their purpose.
734 public static boolean isInitialStandbyPOD() {
735 return thisPod.equals(initialStandbyPod);
739 * INSERT an {@link Insertable} bean into the database.
741 * @param bean the bean representing a row to insert
742 * @return true if the INSERT was successful
744 protected boolean doInsert(Insertable bean) {
747 Connection conn = null;
749 conn = db.getConnection();
750 rv = bean.doInsert(conn);
751 } catch (SQLException e) {
753 intlogger.warn("PROV0005 doInsert: " + e.getMessage(), e);
763 * UPDATE an {@link Updateable} bean in the database.
765 * @param bean the bean representing a row to update
766 * @return true if the UPDATE was successful
768 protected boolean doUpdate(Updateable bean) {
771 Connection conn = null;
773 conn = db.getConnection();
774 rv = bean.doUpdate(conn);
775 } catch (SQLException e) {
777 intlogger.warn("PROV0006 doUpdate: " + e.getMessage(), e);
787 * DELETE an {@link Deleteable} bean from the database.
789 * @param bean the bean representing a row to delete
790 * @return true if the DELETE was successful
792 protected boolean doDelete(Deleteable bean) {
795 Connection conn = null;
797 conn = db.getConnection();
798 rv = bean.doDelete(conn);
799 } catch (SQLException e) {
801 intlogger.warn("PROV0007 doDelete: " + e.getMessage(), e);
810 private static boolean getBoolean(Map<String, String> map, String name) {
811 String s = map.get(name);
812 return (s != null) && s.equalsIgnoreCase("true");
815 private static String getString(Map<String, String> map, String name, String dflt) {
816 String s = map.get(name);
817 return (s != null) ? s : dflt;
820 private static int getInt(Map<String, String> map, String name, int dflt) {
822 String s = map.get(name);
823 return Integer.parseInt(s);
824 } catch (NumberFormatException e) {
829 private static Set<String> getSet(Map<String, String> map, String name) {
830 Set<String> set = new HashSet<>();
831 String s = map.get(name);
833 String[] pp = s.split("\\|");
835 for (String t : pp) {
836 String t2 = t.trim();
837 if (t2.length() > 0) {
847 * A class used to encapsulate a Content-type header, separating out the "version" attribute (which defaults to
850 public class ContentHeader {
852 private String type = "";
853 private Map<String, String> map = new HashMap<>();
859 ContentHeader(String t, String v) {
861 map.put("version", v);
864 public String getType() {
868 public String getAttribute(String key) {
869 String s = map.get(key);
878 * Get the ContentHeader from an HTTP request.
880 * @param req the request
881 * @return the header, encapsulated in a ContentHeader object
883 ContentHeader getContentHeader(HttpServletRequest req) {
884 ContentHeader ch = new ContentHeader();
885 String s = req.getHeader("Content-Type");
887 String[] pp = s.split(";");
888 ch.type = pp[0].trim();
889 for (int i = 1; i < pp.length; i++) {
890 int ix = pp[i].indexOf('=');
892 String k = pp[i].substring(0, ix).trim();
893 String v = pp[i].substring(ix + 1).trim();
896 ch.map.put(pp[i].trim(), "");
903 // Methods for the Policy Engine classes - ProvDataProvider interface
905 public String getFeedOwner(String feedId) {
907 int n = Integer.parseInt(feedId);
908 Feed f = Feed.getFeedById(n);
910 return f.getPublisher();
912 } catch (NumberFormatException e) {
919 public String getFeedClassification(String feedId) {
921 int n = Integer.parseInt(feedId);
922 Feed f = Feed.getFeedById(n);
924 return f.getAuthorization().getClassification();
926 } catch (NumberFormatException e) {
933 public String getSubscriptionOwner(String subId) {
935 int n = Integer.parseInt(subId);
936 Subscription s = Subscription.getSubscriptionById(n);
938 return s.getSubscriber();
940 } catch (NumberFormatException e) {
947 * @Method - isUserMemberOfGroup - Rally:US708115
948 * @Params - group object and user to check if exists in given group
949 * @return - boolean value /true/false
951 private boolean isUserMemberOfGroup(Group group, String user) {
953 String groupDetails = group.getMembers().replace("]", "").replace("[", "");
954 String[] s = groupDetails.split("},");
956 for (String value : s) {
959 jsonObj = new JSONObject(value + "}");
960 if (jsonObj.get("id").equals(user)) {
963 } catch (JSONException e) {
964 intlogger.error("JSONException: " + e.getMessage(), e);
972 * @Method - getGroupByFeedGroupId- Rally:US708115
973 * @Params - User to check in group and feedid which is assigned the group.
974 * @return - string value grupid/null
977 public String getGroupByFeedGroupId(String owner, String feedId) {
979 int n = Integer.parseInt(feedId);
980 Feed f = Feed.getFeedById(n);
982 int groupid = f.getGroupid();
984 Group group = Group.getGroupById(groupid);
985 assert group != null;
986 if (isUserMemberOfGroup(group, owner)) {
987 return group.getAuthid();
991 } catch (NumberFormatException e) {
998 * @Method - getGroupBySubGroupId - Rally:US708115
999 * @Params - User to check in group and subid which is assigned the group.
1000 * @return - string value grupid/null
1003 public String getGroupBySubGroupId(String owner, String subId) {
1005 int n = Integer.parseInt(subId);
1006 Subscription s = Subscription.getSubscriptionById(n);
1008 int groupid = s.getGroupid();
1010 Group group = Group.getGroupById(groupid);
1011 assert group != null;
1012 if (isUserMemberOfGroup(group, owner)) {
1013 return group.getAuthid();
1017 } catch (NumberFormatException e) {
1024 * @Method - setIpFqdnRequestIDandInvocationIDForEelf
1025 * @Params - method, prints method name in EELF log.
1026 * @Params- Req, Request used to get RequestId and InvocationId
1028 void setIpFqdnRequestIDandInvocationIDForEelf(String method, HttpServletRequest req) {
1029 setIpFqdnForEelf(method);
1030 setMDC(req, "X-ONAP-RequestID", MDC_KEY_REQUEST_ID);
1031 setMDC(req, "X-InvocationID", "InvocationId");
1034 private void setMDC(HttpServletRequest req, String headerName, String keyName) {
1035 String mdcId = req.getHeader(headerName);
1036 if (StringUtils.isBlank(mdcId)) {
1037 mdcId = UUID.randomUUID().toString();
1039 MDC.put(keyName, mdcId);
1043 * @Method - setIpFqdnRequestIdForEelf - Rally:US664892
1044 * @Params - method, prints method name in EELF log.
1046 void setIpFqdnForEelf(String method) {
1048 MDC.put(MDC_SERVICE_NAME, method);
1050 MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName());
1051 MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
1052 } catch (Exception e) {
1053 intlogger.error("Exception: " + e.getMessage(), e);
1059 * AAF changes: TDP EPIC US# 307413
1060 * @Method - getFeedPermission - Forming permission string for feed part to check AAF access in CADI Framework
1061 * @Params - aafInstance Passing aafInstance as it's used in permission string
1062 * @Params - userAction Passing CONST values to set different actions in permission string
1064 String getFeedPermission(String aafInstance, String userAction) {
1066 Properties props = (new DB()).getProperties();
1067 String type = props.getProperty(AAF_CADI_FEED_TYPE, AAF_CADI_FEED);
1069 switch (userAction) {
1070 case CREATE_PERMISSION:
1071 action = CREATE_PERMISSION;
1073 case EDIT_PERMISSION:
1074 action = EDIT_PERMISSION;
1076 case DELETE_PERMISSION:
1077 action = DELETE_PERMISSION;
1079 case PUBLISH_PERMISSION:
1080 action = PUBLISH_PERMISSION;
1082 case SUSPEND_PERMISSION:
1083 action = SUSPEND_PERMISSION;
1085 case RESTORE_PERMISSION:
1086 action = RESTORE_PERMISSION;
1091 if (aafInstance == null || aafInstance.equals("")) {
1092 aafInstance = props.getProperty(AAF_INSTANCE, "org.onap.dmaap-dr.NoInstanceDefined");
1094 return type + "|" + aafInstance + "|" + action;
1095 } catch (Exception e) {
1096 intlogger.error("PROV7005 BaseServlet.getFeedPermission: " + e.getMessage(), e);
1102 * AAF changes: TDP EPIC US# 307413
1103 * @Method - getSubscriberPermission - Forming permission string for subscription part to check AAF access in CADI Framework
1104 * @Params - aafInstance Passing aafInstance as it's used in permission string
1105 * @Params - userAction Passing CONST values to set different actions in permission string
1107 String getSubscriberPermission(String aafInstance, String userAction) {
1109 Properties props = (new DB()).getProperties();
1110 String type = props.getProperty(AAF_CADI_SUB_TYPE, AAF_CADI_SUB);
1112 switch (userAction) {
1113 case SUBSCRIBE_PERMISSION:
1114 action = SUBSCRIBE_PERMISSION;
1115 type = props.getProperty(AAF_CADI_FEED_TYPE, AAF_CADI_FEED);
1117 case EDIT_PERMISSION:
1118 action = EDIT_PERMISSION;
1120 case DELETE_PERMISSION:
1121 action = DELETE_PERMISSION;
1123 case RESTORE_PERMISSION:
1124 action = RESTORE_PERMISSION;
1126 case SUSPEND_PERMISSION:
1127 action = SUSPEND_PERMISSION;
1129 case PUBLISH_PERMISSION:
1130 action = PUBLISH_PERMISSION;
1132 case APPROVE_SUB_PERMISSION:
1133 action = APPROVE_SUB_PERMISSION;
1134 type = props.getProperty(AAF_CADI_FEED_TYPE, AAF_CADI_FEED);
1139 if (aafInstance == null || aafInstance.equals("")) {
1140 aafInstance = props.getProperty(AAF_INSTANCE, "org.onap.dmaap-dr.NoInstanceDefined");
1142 return type + "|" + aafInstance + "|" + action;
1143 } catch (Exception e) {
1144 intlogger.error("PROV7005 BaseServlet.getSubscriberPermission: " + e.getMessage(), e);