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_KEY_REQUEST_ID;
28 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;
32 import com.att.eelf.configuration.EELFLogger;
33 import com.att.eelf.configuration.EELFManager;
34 import java.net.InetAddress;
35 import java.net.UnknownHostException;
36 import java.security.GeneralSecurityException;
37 import java.security.cert.X509Certificate;
38 import java.sql.Connection;
39 import java.sql.SQLException;
40 import java.util.ArrayList;
41 import java.util.HashMap;
42 import java.util.HashSet;
43 import java.util.List;
45 import java.util.Properties;
47 import java.util.UUID;
48 import javax.servlet.ServletConfig;
49 import javax.servlet.ServletException;
50 import javax.servlet.http.HttpServlet;
51 import javax.servlet.http.HttpServletRequest;
52 import org.apache.commons.lang3.StringUtils;
53 import org.jetbrains.annotations.Nullable;
54 import org.json.JSONArray;
55 import org.json.JSONException;
56 import org.json.JSONObject;
57 import org.json.JSONTokener;
58 import org.onap.dmaap.datarouter.authz.Authorizer;
59 import org.onap.dmaap.datarouter.authz.impl.ProvAuthorizer;
60 import org.onap.dmaap.datarouter.authz.impl.ProvDataProvider;
61 import org.onap.dmaap.datarouter.provisioning.beans.Deleteable;
62 import org.onap.dmaap.datarouter.provisioning.beans.Feed;
63 import org.onap.dmaap.datarouter.provisioning.beans.Group;
64 import org.onap.dmaap.datarouter.provisioning.beans.Insertable;
65 import org.onap.dmaap.datarouter.provisioning.beans.NodeClass;
66 import org.onap.dmaap.datarouter.provisioning.beans.Parameters;
67 import org.onap.dmaap.datarouter.provisioning.beans.Subscription;
68 import org.onap.dmaap.datarouter.provisioning.beans.Updateable;
69 import org.onap.dmaap.datarouter.provisioning.utils.DB;
70 import org.onap.dmaap.datarouter.provisioning.utils.PasswordProcessor;
71 import org.onap.dmaap.datarouter.provisioning.utils.ThrottleFilter;
76 * This is the base class for all Servlets in the provisioning code. It provides standard constants and some common
80 * @version $Id: BaseServlet.java,v 1.16 2014/03/12 19:45:40 eby Exp $
82 @SuppressWarnings("serial")
83 public class BaseServlet extends HttpServlet implements ProvDataProvider {
85 public static final String BEHALF_HEADER = "X-DMAAP-DR-ON-BEHALF-OF";
87 public static final String EXCLUDE_AAF_HEADER = "X-EXCLUDE-AAF";
89 private static final String AAF_CADI_FEED_TYPE = "org.onap.dmaap.datarouter.provserver.aaf.feed.type";
90 private static final String AAF_CADI_SUB_TYPE = "org.onap.dmaap.datarouter.provserver.aaf.sub.type";
91 private static final String AAF_INSTANCE = "org.onap.dmaap.datarouter.provserver.aaf.instance";
92 private static final String AAF_CADI_FEED = "org.onap.dmaap-dr.feed";
93 private static final String AAF_CADI_SUB = "org.onap.dmaap-dr.sub";
95 static final String CREATE_PERMISSION = "create";
96 static final String EDIT_PERMISSION = "edit";
97 static final String DELETE_PERMISSION = "delete";
98 private static final String PUBLISH_PERMISSION = "publish";
99 private static final String SUSPEND_PERMISSION = "suspend";
100 private static final String RESTORE_PERMISSION = "restore";
101 private static final String SUBSCRIBE_PERMISSION = "subscribe";
102 static final String APPROVE_SUB_PERMISSION = "approveSub";
104 static final String FEED_BASECONTENT_TYPE = "application/vnd.dmaap-dr.feed";
105 public static final String FEED_CONTENT_TYPE = "application/vnd.dmaap-dr.feed; version=2.0";
106 public static final String FEEDFULL_CONTENT_TYPE = "application/vnd.dmaap-dr.feed-full; version=2.0";
107 public static final String FEEDLIST_CONTENT_TYPE = "application/vnd.dmaap-dr.feed-list; version=1.0";
108 static final String SUB_BASECONTENT_TYPE = "application/vnd.dmaap-dr.subscription";
109 public static final String SUB_CONTENT_TYPE = "application/vnd.dmaap-dr.subscription; version=2.0";
110 public static final String SUBFULL_CONTENT_TYPE = "application/vnd.dmaap-dr.subscription-full; version=2.0";
111 static final String SUBLIST_CONTENT_TYPE = "application/vnd.dmaap-dr.subscription-list; version=1.0";
114 //Adding groups functionality, ...1610
115 static final String GROUP_BASECONTENT_TYPE = "application/vnd.dmaap-dr.group";
116 static final String GROUP_CONTENT_TYPE = "application/vnd.dmaap-dr.group; version=2.0";
117 static final String GROUPFULL_CONTENT_TYPE = "application/vnd.dmaap-dr.group-full; version=2.0";
118 public static final String GROUPLIST_CONTENT_TYPE = "application/vnd.dmaap-dr.fegrouped-list; version=1.0";
121 public static final String LOGLIST_CONTENT_TYPE = "application/vnd.dmaap-dr.log-list; version=1.0";
122 public static final String PROVFULL_CONTENT_TYPE1 = "application/vnd.dmaap-dr.provfeed-full; version=1.0";
123 public static final String PROVFULL_CONTENT_TYPE2 = "application/vnd.dmaap-dr.provfeed-full; version=2.0";
124 public static final String CERT_ATTRIBUTE = "javax.servlet.request.X509Certificate";
126 static final String DB_PROBLEM_MSG = "There has been a problem with the DB. It is suggested you try the operation again.";
128 private static final int DEFAULT_MAX_FEEDS = 10000;
129 private static final int DEFAULT_MAX_SUBS = 100000;
130 private static final int DEFAULT_POKETIMER1 = 5;
131 private static final int DEFAULT_POKETIMER2 = 30;
132 private static final String DEFAULT_DOMAIN = "onap";
133 private static final String DEFAULT_PROVSRVR_NAME = "dmaap-dr-prov";
136 static final String MISSING_ON_BEHALF = "Missing X-DMAAP-DR-ON-BEHALF-OF header.";
137 static final String MISSING_FEED = "Missing or bad feed number.";
138 static final String POLICY_ENGINE = "Policy Engine disallows access.";
139 static final String UNAUTHORIZED = "Unauthorized.";
140 static final String BAD_SUB = "Missing or bad subscription number.";
141 static final String BAD_JSON = "Badly formed JSON";
142 static final String BAD_URL = "Bad URL.";
144 public static final String API = "/api/";
145 static final String LOGS = "/logs/";
146 static final String TEXT_CT = "text/plain";
147 static final String INGRESS = "/ingress/";
148 static final String EGRESS = "/egress/";
149 static final String NETWORK = "/network/";
150 static final String GROUPID = "groupid";
151 public static final String FEEDID = "feedid";
152 static final String FEEDIDS = "feedids";
153 static final String SUBID = "subid";
154 static final String EVENT_TYPE = "eventType";
155 static final String OUTPUT_TYPE = "output_type";
156 static final String START_TIME = "start_time";
157 static final String END_TIME = "end_time";
158 static final String REASON_SQL = "reasonSQL";
162 * A boolean to trigger one time "provisioning changed" event on startup.
164 private static boolean startmsgFlag = true;
166 * This POD should require SSL connections from clients; pulled from the DB (PROV_REQUIRE_SECURE).
168 private static boolean requireSecure = true;
170 * This POD should require signed, recognized certificates from clients; pulled from the DB (PROV_REQUIRE_CERT).
172 private static boolean requireCert = true;
174 * The set of authorized addresses and networks; pulled from the DB (PROV_AUTH_ADDRESSES).
176 private static Set<String> authorizedAddressesAndNetworks = new HashSet<>();
178 * The set of authorized names; pulled from the DB (PROV_AUTH_SUBJECTS).
180 private static Set<String> authorizedNames = new HashSet<>();
182 * The FQDN of the initially "active" provisioning server in this Data Router ecosystem.
184 private static String initialActivePod;
186 * The FQDN of the initially "standby" provisioning server in this Data Router ecosystem.
188 private static String initialStandbyPod;
190 * The FQDN of this provisioning server in this Data Router ecosystem.
192 private static String thisPod;
194 * "Timer 1" - used to determine when to notify nodes of provisioning changes.
196 private static long pokeTimer1;
198 * "Timer 2" - used to determine when to notify nodes of provisioning changes.
200 private static long pokeTimer2;
202 * Array of nodes names and/or FQDNs.
204 private static String[] nodes = new String[0];
206 * [DATARTR-27] Poke all the DR nodes : Array of nodes names and/or FQDNs.
208 private static String[] drnodes = new String[0];
210 * Array of node IP addresses.
212 private static InetAddress[] nodeAddresses = new InetAddress[0];
214 * Array of POD IP addresses.
216 private static InetAddress[] podAddresses = new InetAddress[0];
218 * The maximum number of feeds allowed; pulled from the DB (PROV_MAXFEED_COUNT).
220 static int maxFeeds = 0;
222 * The maximum number of subscriptions allowed; pulled from the DB (PROV_MAXSUB_COUNT).
224 static int maxSubs = 0;
226 * The current number of feeds in the system.
228 static int activeFeeds = 0;
230 * The current number of subscriptions in the system.
232 static int activeSubs = 0;
235 * The domain used to generate a FQDN from the "bare" node names.
237 private static String provDomain = "web.att.com";
240 * The standard FQDN of the provisioning server in this Data Router ecosystem.
242 private static String provName = "feeds-drtr.web.att.com";
245 * The standard FQDN of the ACTIVE_POD provisioning server in this Data Router ecosystem.
247 private static String activeProvName = "feeds-drtr.web.att.com";
250 * This logger is used to log provisioning events.
252 protected static EELFLogger eventlogger;
254 * This logger is used to log internal events (errors, etc.)
256 protected static EELFLogger intlogger;
258 * Authorizer - interface to the Policy Engine.
260 protected static Authorizer authz;
262 * The Synchronizer used to sync active DB to standby one.
264 private static SynchronizerTask synctask = null;
266 //Data Router Subscriber HTTPS Relaxation feature USERSTORYID:US674047.
267 private InetAddress thishost;
268 private InetAddress loopback;
270 //DMAAP-597 (Tech Dept) REST request source IP auth relaxation to accommodate OOM kubernetes deploy
271 private static String isAddressAuthEnabled = (new DB()).getProperties()
272 .getProperty("org.onap.dmaap.datarouter.provserver.isaddressauthenabled", "false");
274 static String isCadiEnabled = (new DB()).getProperties()
275 .getProperty("org.onap.dmaap.datarouter.provserver.cadi.enabled", "false");
278 * Initialize data common to all the provisioning server servlets.
280 protected BaseServlet() {
281 if (eventlogger == null) {
282 eventlogger = EELFManager.getInstance().getLogger("EventLog");
284 if (intlogger == null) {
285 this.intlogger = EELFManager.getInstance().getLogger("InternalLog");
288 authz = new ProvAuthorizer(this);
291 startmsgFlag = false;
292 provisioningParametersChanged();
294 if (synctask == null) {
295 synctask = SynchronizerTask.getSynchronizer();
297 String name = this.getClass().getName();
298 intlogger.info("PROV0002 Servlet " + name + " started.");
302 public void init(ServletConfig config) throws ServletException {
305 thishost = InetAddress.getLocalHost();
306 loopback = InetAddress.getLoopbackAddress();
307 } catch (UnknownHostException e) {
308 intlogger.info("BaseServlet.init: " + e.getMessage(), e);
312 public static int getIdFromPath(HttpServletRequest req) {
313 String path = req.getPathInfo();
314 if (path == null || path.length() < 2) {
318 return Integer.parseInt(path.substring(1));
319 } catch (NumberFormatException e) {
325 * Read the request's input stream and return a JSONObject from it.
327 * @param req the HTTP request
328 * @return the JSONObject, or null if the stream cannot be parsed
330 JSONObject getJSONfromInput(HttpServletRequest req) {
331 JSONObject jo = null;
333 jo = new JSONObject(new JSONTokener(req.getInputStream()));
334 if (intlogger.isDebugEnabled()) {
335 intlogger.debug("JSON: " + jo.toString());
337 } catch (Exception e) {
338 intlogger.info("Error reading JSON: " + e);
344 * This method encrypt/decrypt the key in the JSON passed by user request inside the authorisation
345 * header object in request before logging the JSON.
347 * @param jo the JSON passed in http request.
348 * @param maskKey the key to be masked in the JSON passed.
349 * @param action whether to mask the key or unmask it in a JSON passed.
350 * @return the JSONObject, or null if the stream cannot be parsed.
352 static JSONObject maskJSON(JSONObject jo, String maskKey, boolean action) {
353 if (!jo.isNull("authorization")) {
354 JSONArray endpointIds = jo.getJSONObject("authorization").getJSONArray("endpoint_ids");
355 for (int index = 0; index < endpointIds.length(); index++) {
356 if ((!endpointIds.getJSONObject(index).isNull(maskKey))) {
357 String password = endpointIds.getJSONObject(index).get(maskKey).toString();
358 processPassword(maskKey, action, endpointIds, index, password);
365 private static void processPassword(String maskKey, boolean action, JSONArray endpointIds, int index,
369 endpointIds.getJSONObject(index).put(maskKey, PasswordProcessor.encrypt(password));
371 endpointIds.getJSONObject(index).put(maskKey, PasswordProcessor.decrypt(password));
373 } catch (JSONException | GeneralSecurityException e) {
374 intlogger.info("Error reading JSON while masking: " + e);
379 * Check if the remote host is authorized to perform provisioning. Is the request secure? Is it coming from an
380 * authorized IP address or network (configured via PROV_AUTH_ADDRESSES)? Does it have a valid client certificate
381 * (configured via PROV_AUTH_SUBJECTS)?
383 * @param request the request
384 * @return an error string, or null if all is OK
386 String isAuthorizedForProvisioning(HttpServletRequest request) {
387 if (!Boolean.parseBoolean(isAddressAuthEnabled)) {
390 // Is the request https?
391 if (requireSecure && !request.isSecure()) {
392 return "Request must be made over an HTTPS connection.";
394 String remoteHostCheck = checkRemoteHostAuthorization(request);
395 if (remoteHostCheck != null) {
396 return remoteHostCheck;
398 // Does remote have a valid certificate?
400 X509Certificate[] certs = (X509Certificate[]) request.getAttribute(CERT_ATTRIBUTE);
401 if (certs == null || certs.length == 0) {
402 return "Client certificate is missing.";
404 // cert[0] is the client cert
405 // see http://www.proto.research.att.com/java/java7/api/javax/net/ssl/SSLSession.html#getPeerCertificates()
406 String name = certs[0].getSubjectX500Principal().getName();
407 if (!authorizedNames.contains(name)) {
408 return "No authorized certificate found.";
416 private String checkRemoteHostAuthorization(HttpServletRequest request) {
417 // Is remote IP authorized?
418 String remote = request.getRemoteAddr();
420 boolean found = false;
421 InetAddress ip = InetAddress.getByName(remote);
422 for (String addrnet : authorizedAddressesAndNetworks) {
423 found |= addressMatchesNetwork(ip, addrnet);
426 return "Unauthorized address: " + remote;
428 } catch (UnknownHostException e) {
429 intlogger.error("PROV0051 BaseServlet.isAuthorizedForProvisioning: " + e.getMessage(), e);
430 return "Unauthorized address: " + remote;
436 * Check if the remote IP address is authorized to see the /internal URL tree.
438 * @param request the HTTP request
439 * @return true iff authorized
441 boolean isAuthorizedForInternal(HttpServletRequest request) {
443 if (!Boolean.parseBoolean(isAddressAuthEnabled)) {
446 InetAddress ip = InetAddress.getByName(request.getRemoteAddr());
447 for (InetAddress node : getNodeAddresses()) {
448 if (ip.equals(node)) {
452 for (InetAddress pod : getPodAddresses()) {
453 if (ip.equals(pod)) {
457 if (ip.equals(thishost)) {
460 if (ip.equals(loopback)) {
463 } catch (UnknownHostException e) {
464 intlogger.error("PROV0052 BaseServlet.isAuthorizedForInternal: " + e.getMessage(), e);
470 * Check if an IP address matches a network address.
472 * @param ip the IP address
473 * @param s the network address; a bare IP address may be matched also
474 * @return true if they intersect
476 private static boolean addressMatchesNetwork(InetAddress ip, String s) {
478 int n = s.indexOf('/');
480 mlen = Integer.parseInt(s.substring(n + 1));
481 s = s.substring(0, n);
484 InetAddress i2 = InetAddress.getByName(s);
485 byte[] b1 = ip.getAddress();
486 byte[] b2 = i2.getAddress();
487 if (b1.length != b2.length) {
492 (byte) 0x00, (byte) 0x80, (byte) 0xC0, (byte) 0xE0,
493 (byte) 0xF0, (byte) 0xF8, (byte) 0xFC, (byte) 0xFE
495 byte mask = masks[mlen % 8];
496 for (n = mlen / 8; n < b1.length; n++) {
502 for (n = 0; n < b1.length; n++) {
503 if (b1[n] != b2[n]) {
507 } catch (UnknownHostException e) {
508 intlogger.error("PROV0053 BaseServlet.addressMatchesNetwork: " + e.getMessage(), e);
515 * Something has changed in the provisioning data. Start the timers that will cause the pre-packaged JSON string to
516 * be regenerated, and cause nodes and the other provisioning server to be notified.
518 static void provisioningDataChanged() {
519 long now = System.currentTimeMillis();
520 Poker p = Poker.getPoker();
521 p.setTimers(now + (pokeTimer1 * 1000L), now + (pokeTimer2 * 1000L));
525 * Something in the parameters has changed, reload all parameters from the DB.
527 static void provisioningParametersChanged() {
528 Map<String, String> map = Parameters.getParameters();
529 requireSecure = getBoolean(map, Parameters.PROV_REQUIRE_SECURE);
530 requireCert = getBoolean(map, Parameters.PROV_REQUIRE_CERT);
531 authorizedAddressesAndNetworks = getSet(map, Parameters.PROV_AUTH_ADDRESSES);
532 authorizedNames = getSet(map, Parameters.PROV_AUTH_SUBJECTS);
533 nodes = getSet(map, Parameters.NODES).toArray(new String[0]);
534 maxFeeds = getInt(map, Parameters.PROV_MAXFEED_COUNT, DEFAULT_MAX_FEEDS);
535 maxSubs = getInt(map, Parameters.PROV_MAXSUB_COUNT, DEFAULT_MAX_SUBS);
536 pokeTimer1 = getInt(map, Parameters.PROV_POKETIMER1, DEFAULT_POKETIMER1);
537 pokeTimer2 = getInt(map, Parameters.PROV_POKETIMER2, DEFAULT_POKETIMER2);
539 // The domain used to generate a FQDN from the "bare" node names
540 provDomain = getString(map, Parameters.PROV_DOMAIN, DEFAULT_DOMAIN);
541 provName = getString(map, Parameters.PROV_NAME, DEFAULT_PROVSRVR_NAME);
542 activeProvName = getString(map, Parameters.PROV_ACTIVE_NAME, provName);
543 initialActivePod = getString(map, Parameters.ACTIVE_POD, "");
544 initialStandbyPod = getString(map, Parameters.STANDBY_POD, "");
546 //Adding new param for static Routing - Rally:US664862-1610
547 String staticRoutingNodes = getString(map, Parameters.STATIC_ROUTING_NODES, "");
548 activeFeeds = Feed.countActiveFeeds();
549 activeSubs = Subscription.countActiveSubscriptions();
551 thisPod = InetAddress.getLocalHost().getHostName();
552 } catch (UnknownHostException e) {
554 intlogger.warn("PROV0014 Cannot determine the name of this provisioning server.", e);
557 // Normalize the nodes, and fill in nodeAddresses
558 InetAddress[] na = new InetAddress[nodes.length];
559 for (int i = 0; i < nodes.length; i++) {
561 na[i] = InetAddress.getByName(nodes[i]);
562 intlogger.debug("PROV0003 DNS lookup: " + nodes[i] + " => " + na[i].toString());
563 } catch (UnknownHostException e) {
565 intlogger.warn("PROV0004 Cannot lookup " + nodes[i] + ": " + e.getMessage(), e);
569 //[DATARTR-27] Poke all the DR nodes: assigning DR Nodes
570 drnodes = nodes.clone();
572 //Reset Nodes arr after - removing static routing Nodes, Rally Userstory - US664862 .
573 List<String> filterNodes = new ArrayList<>();
574 for (String node : nodes) {
575 if (!staticRoutingNodes.contains(node)) {
576 filterNodes.add(node);
579 nodes = filterNodes.toArray(new String[0]);
582 NodeClass.setNodes(nodes); // update NODES table
584 // Normalize the PODs, and fill in podAddresses
585 String[] pods = getPods();
586 na = new InetAddress[pods.length];
587 for (int i = 0; i < pods.length; i++) {
589 na[i] = InetAddress.getByName(pods[i]);
590 intlogger.debug("PROV0003 DNS lookup: " + pods[i] + " => " + na[i].toString());
591 } catch (UnknownHostException e) {
593 intlogger.warn("PROV0004 Cannot lookup " + pods[i] + ": " + e.getMessage(), e);
598 // Update ThrottleFilter
599 ThrottleFilter.configure();
601 // Check if we are active or standby POD
602 if (!isInitialActivePOD() && !isInitialStandbyPOD()) {
603 intlogger.warn("PROV0015 This machine is neither the active nor the standby POD.");
607 public static String getProvName() {
611 static String getActiveProvName() {
612 return activeProvName;
616 * Get an array of all node names in the DR network.
618 * @return an array of Strings
620 public static String[] getNodes() {
625 * Get an array of all node InetAddresses in the DR network.
627 * @return an array of InetAddresses
629 private static InetAddress[] getNodeAddresses() {
630 return nodeAddresses;
634 * Get an array of all POD names in the DR network.
636 * @return an array of Strings
638 public static String[] getPods() {
639 return new String[]{initialActivePod, initialStandbyPod};
643 * Get an array of all POD InetAddresses in the DR network.
645 * @return an array of InetAddresses
647 private static InetAddress[] getPodAddresses() {
652 * Gets the FQDN of the initially ACTIVE_POD provisioning server (POD). Note: this used to be called isActivePOD(),
653 * however, that is a misnomer, as the active status could shift to the standby POD without these parameters
654 * changing. Hence, the function names have been changed to more accurately reflect their purpose.
658 public static boolean isInitialActivePOD() {
659 return thisPod.equals(initialActivePod);
663 * Gets the FQDN of the initially STANDBY_POD provisioning server (POD). Note: this used to be called isStandbyPOD(),
664 * however, that is a misnomer, as the standby status could shift to the active POD without these parameters
665 * changing. Hence, the function names have been changed to more accurately reflect their purpose.
669 public static boolean isInitialStandbyPOD() {
670 return thisPod.equals(initialStandbyPod);
674 * INSERT an {@link Insertable} bean into the database.
676 * @param bean the bean representing a row to insert
677 * @return true if the INSERT was successful
679 protected boolean doInsert(Insertable bean) {
682 Connection conn = null;
684 conn = db.getConnection();
685 rv = bean.doInsert(conn);
686 } catch (SQLException e) {
688 intlogger.warn("PROV0005 doInsert: " + e.getMessage(), e);
698 * UPDATE an {@link Updateable} bean in the database.
700 * @param bean the bean representing a row to update
701 * @return true if the UPDATE was successful
703 protected boolean doUpdate(Updateable bean) {
706 Connection conn = null;
708 conn = db.getConnection();
709 rv = bean.doUpdate(conn);
710 } catch (SQLException e) {
712 intlogger.warn("PROV0006 doUpdate: " + e.getMessage(), e);
722 * DELETE an {@link Deleteable} bean from the database.
724 * @param bean the bean representing a row to delete
725 * @return true if the DELETE was successful
727 protected boolean doDelete(Deleteable bean) {
730 Connection conn = null;
732 conn = db.getConnection();
733 rv = bean.doDelete(conn);
734 } catch (SQLException e) {
736 intlogger.warn("PROV0007 doDelete: " + e.getMessage(), e);
745 private static boolean getBoolean(Map<String, String> map, String name) {
746 String s = map.get(name);
747 return "true".equalsIgnoreCase(s);
750 private static String getString(Map<String, String> map, String name, String dflt) {
751 String s = map.get(name);
752 return (s != null) ? s : dflt;
755 private static int getInt(Map<String, String> map, String name, int dflt) {
757 String s = map.get(name);
758 return Integer.parseInt(s);
759 } catch (NumberFormatException e) {
764 private static Set<String> getSet(Map<String, String> map, String name) {
765 Set<String> set = new HashSet<>();
766 String s = map.get(name);
768 String[] pp = s.split("\\|");
770 for (String t : pp) {
771 String t2 = t.trim();
772 if (t2.length() > 0) {
782 * A class used to encapsulate a Content-type header, separating out the "version" attribute (which defaults to
785 public class ContentHeader {
788 private Map<String, String> map = new HashMap<>();
794 ContentHeader(String t, String v) {
796 map.put("version", v);
799 public String getType() {
803 String getAttribute(String key) {
804 String s = map.get(key);
813 * Get the ContentHeader from an HTTP request.
815 * @param req the request
816 * @return the header, encapsulated in a ContentHeader object
818 ContentHeader getContentHeader(HttpServletRequest req) {
819 ContentHeader ch = new ContentHeader();
820 String s = req.getHeader("Content-Type");
822 String[] pp = s.split(";");
823 ch.type = pp[0].trim();
824 for (int i = 1; i < pp.length; i++) {
825 int ix = pp[i].indexOf('=');
827 String k = pp[i].substring(0, ix).trim();
828 String v = pp[i].substring(ix + 1).trim();
831 ch.map.put(pp[i].trim(), "");
838 // Methods for the Policy Engine classes - ProvDataProvider interface
840 public String getFeedOwner(String feedId) {
842 int n = Integer.parseInt(feedId);
843 Feed f = Feed.getFeedById(n);
845 return f.getPublisher();
847 } catch (NumberFormatException e) {
854 public String getFeedClassification(String feedId) {
856 int n = Integer.parseInt(feedId);
857 Feed f = Feed.getFeedById(n);
859 return f.getAuthorization().getClassification();
861 } catch (NumberFormatException e) {
868 public String getSubscriptionOwner(String subId) {
870 int n = Integer.parseInt(subId);
871 Subscription s = Subscription.getSubscriptionById(n);
873 return s.getSubscriber();
875 } catch (NumberFormatException e) {
882 * @Method - isUserMemberOfGroup - Rally:US708115
883 * @Params - group object and user to check if exists in given group
884 * @return - boolean value /true/false
886 private boolean isUserMemberOfGroup(Group group, String user) {
888 String groupDetails = group.getMembers().replace("]", "").replace("[", "");
889 String[] s = groupDetails.split("},");
891 for (String value : s) {
894 jsonObj = new JSONObject(value + "}");
895 if (jsonObj.get("id").equals(user)) {
898 } catch (JSONException e) {
899 intlogger.error("JSONException: " + e.getMessage(), e);
907 * @Method - getGroupByFeedGroupId- Rally:US708115
908 * @Params - User to check in group and feedid which is assigned the group.
909 * @return - string value groupid/null
912 public String getGroupByFeedGroupId(String owner, String feedId) {
914 Feed f = Feed.getFeedById(Integer.parseInt(feedId));
916 int groupid = f.getGroupid();
918 Group group = Group.getGroupById(groupid);
919 if (group != null && isUserMemberOfGroup(group, owner)) {
920 return group.getAuthid();
924 } catch (NumberFormatException e) {
931 * @Method - getGroupBySubGroupId - Rally:US708115
932 * @Params - User to check in group and subid which is assigned the group.
933 * @return - string value groupid/null
936 public String getGroupBySubGroupId(String owner, String subId) {
938 int n = Integer.parseInt(subId);
939 Subscription s = Subscription.getSubscriptionById(n);
941 int groupid = s.getGroupid();
943 Group group = Group.getGroupById(groupid);
944 if (group != null && isUserMemberOfGroup(group, owner)) {
945 return group.getAuthid();
949 } catch (NumberFormatException e) {
956 * @Method - setIpFqdnRequestIDandInvocationIDForEelf
957 * @Params - method, prints method name in EELF log.
958 * @Params- Req, Request used to get RequestId and InvocationId
960 void setIpFqdnRequestIDandInvocationIDForEelf(String method, HttpServletRequest req) {
961 setIpFqdnForEelf(method);
962 setMDC(req, "X-ONAP-RequestID", MDC_KEY_REQUEST_ID);
963 setMDC(req, "X-InvocationID", "InvocationId");
966 private void setMDC(HttpServletRequest req, String headerName, String keyName) {
967 String mdcId = req.getHeader(headerName);
968 if (StringUtils.isBlank(mdcId)) {
969 mdcId = UUID.randomUUID().toString();
971 MDC.put(keyName, mdcId);
975 * @Method - setIpFqdnRequestIdForEelf - Rally:US664892
976 * @Params - method, prints method name in EELF log.
978 void setIpFqdnForEelf(String method) {
980 MDC.put(MDC_SERVICE_NAME, method);
982 MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName());
983 MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
984 } catch (Exception e) {
985 intlogger.error("Exception: " + e.getMessage(), e);
991 * AAF changes: TDP EPIC US# 307413
992 * @Method - getFeedPermission - Forming permission string for feed part to check AAF access in CADI Framework
993 * @Params - aafInstance Passing aafInstance as it's used in permission string
994 * @Params - userAction Passing CONST values to set different actions in permission string
996 String getFeedPermission(String aafInstance, String userAction) {
998 Properties props = (new DB()).getProperties();
999 String type = props.getProperty(AAF_CADI_FEED_TYPE, AAF_CADI_FEED);
1001 switch (userAction) {
1002 case CREATE_PERMISSION:
1003 action = CREATE_PERMISSION;
1005 case EDIT_PERMISSION:
1006 action = EDIT_PERMISSION;
1008 case DELETE_PERMISSION:
1009 action = DELETE_PERMISSION;
1011 case PUBLISH_PERMISSION:
1012 action = PUBLISH_PERMISSION;
1014 case SUSPEND_PERMISSION:
1015 action = SUSPEND_PERMISSION;
1017 case RESTORE_PERMISSION:
1018 action = RESTORE_PERMISSION;
1023 if (aafInstance == null || "".equals(aafInstance)) {
1024 aafInstance = props.getProperty(AAF_INSTANCE, "org.onap.dmaap-dr.NoInstanceDefined");
1026 return type + "|" + aafInstance + "|" + action;
1027 } catch (Exception e) {
1028 intlogger.error("PROV7005 BaseServlet.getFeedPermission: " + e.getMessage(), e);
1034 * AAF changes: TDP EPIC US# 307413
1035 * @Method - getSubscriberPermission - Forming permission string for subscription part to check AAF access in CADI Framework
1036 * @Params - aafInstance Passing aafInstance as it's used in permission string
1037 * @Params - userAction Passing CONST values to set different actions in permission string
1039 String getSubscriberPermission(String aafInstance, String userAction) {
1041 Properties props = (new DB()).getProperties();
1042 String type = props.getProperty(AAF_CADI_SUB_TYPE, AAF_CADI_SUB);
1044 switch (userAction) {
1045 case SUBSCRIBE_PERMISSION:
1046 action = SUBSCRIBE_PERMISSION;
1047 type = props.getProperty(AAF_CADI_FEED_TYPE, AAF_CADI_FEED);
1049 case EDIT_PERMISSION:
1050 action = EDIT_PERMISSION;
1052 case DELETE_PERMISSION:
1053 action = DELETE_PERMISSION;
1055 case RESTORE_PERMISSION:
1056 action = RESTORE_PERMISSION;
1058 case SUSPEND_PERMISSION:
1059 action = SUSPEND_PERMISSION;
1061 case PUBLISH_PERMISSION:
1062 action = PUBLISH_PERMISSION;
1064 case APPROVE_SUB_PERMISSION:
1065 action = APPROVE_SUB_PERMISSION;
1066 type = props.getProperty(AAF_CADI_FEED_TYPE, AAF_CADI_FEED);
1071 if (aafInstance == null || "".equals(aafInstance)) {
1072 aafInstance = props.getProperty(AAF_INSTANCE, "org.onap.dmaap-dr.NoInstanceDefined");
1074 return type + "|" + aafInstance + "|" + action;
1075 } catch (Exception e) {
1076 intlogger.error("PROV7005 BaseServlet.getSubscriberPermission: " + e.getMessage(), e);