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.node;
28 import java.util.HashSet;
29 import java.util.Hashtable;
30 import java.util.Vector;
33 * Processed configuration for this node.
35 * The NodeConfig represents a processed configuration from the Data Router provisioning server. Each time
36 * configuration data is received from the provisioning server, a new NodeConfig is created and the previous one
39 public class NodeConfig {
42 * Raw configuration entry for a data router node
44 public static class ProvNode {
49 * Construct a node configuration entry.
51 * @param cname The cname of the node.
53 public ProvNode(String cname) {
58 * Get the cname of the node
60 public String getCName() {
66 * Raw configuration entry for a provisioning parameter
68 public static class ProvParam {
74 * Construct a provisioning parameter configuration entry.
76 * @param name The name of the parameter.
77 * @param value The value of the parameter.
79 public ProvParam(String name, String value) {
85 * Get the name of the parameter.
87 public String getName() {
92 * Get the value of the parameter.
94 public String getValue() {
100 * Raw configuration entry for a data feed.
102 public static class ProvFeed {
105 private String logdata;
106 private String status;
109 * Construct a feed configuration entry.
111 * @param id The feed ID of the entry.
112 * @param logdata String for log entries about the entry.
113 * @param status The reason why this feed cannot be used (Feed has been deleted, Feed has been suspended) or
114 * null if it is valid.
116 public ProvFeed(String id, String logdata, String status) {
118 this.logdata = logdata;
119 this.status = status;
123 * Get the feed id of the data feed.
125 public String getId() {
130 * Get the log data of the data feed.
132 public String getLogData() {
137 * Get the status of the data feed.
139 public String getStatus() {
145 * Raw configuration entry for a feed user.
147 public static class ProvFeedUser {
149 private String feedid;
151 private String credentials;
154 * Construct a feed user configuration entry
156 * @param feedid The feed id.
157 * @param user The user that will publish to the feed.
158 * @param credentials The Authorization header the user will use to publish.
160 public ProvFeedUser(String feedid, String user, String credentials) {
161 this.feedid = feedid;
163 this.credentials = credentials;
167 * Get the feed id of the feed user.
169 public String getFeedId() {
174 * Get the user for the feed user.
176 public String getUser() {
181 * Get the credentials for the feed user.
183 public String getCredentials() {
184 return (credentials);
189 * Raw configuration entry for a feed subnet
191 public static class ProvFeedSubnet {
193 private String feedid;
197 * Construct a feed subnet configuration entry
199 * @param feedid The feed ID
200 * @param cidr The CIDR allowed to publish to the feed.
202 public ProvFeedSubnet(String feedid, String cidr) {
203 this.feedid = feedid;
208 * Get the feed id of the feed subnet.
210 public String getFeedId() {
215 * Get the CIDR of the feed subnet.
217 public String getCidr() {
223 * Raw configuration entry for a subscription
225 public static class ProvSubscription {
227 private String subid;
228 private String feedid;
230 private String authuser;
231 private String credentials;
232 private boolean metaonly;
233 private boolean use100;
234 private boolean privilegedSubscriber;
237 * Construct a subscription configuration entry
239 * @param subid The subscription ID
240 * @param feedid The feed ID
241 * @param url The base delivery URL (not including the fileid)
242 * @param authuser The user in the credentials used to deliver
243 * @param credentials The credentials used to authenticate to the delivery URL exactly as they go in the
244 * Authorization header.
245 * @param metaonly Is this a meta data only subscription?
246 * @param use100 Should we send Expect: 100-continue?
247 * @param privilegedSubscriber Can we wait to receive a delete file call before deleting file
249 public ProvSubscription(String subid, String feedid, String url, String authuser, String credentials,
250 boolean metaonly, boolean use100, boolean privilegedSubscriber) {
252 this.feedid = feedid;
254 this.authuser = authuser;
255 this.credentials = credentials;
256 this.metaonly = metaonly;
257 this.use100 = use100;
258 this.privilegedSubscriber = privilegedSubscriber;
262 * Get the subscription ID
264 public String getSubId() {
271 public String getFeedId() {
276 * Get the delivery URL
278 public String getURL() {
285 public String getAuthUser() {
290 * Get the delivery credentials
292 public String getCredentials() {
293 return (credentials);
297 * Is this a meta data only subscription?
299 public boolean isMetaDataOnly() {
304 * Should we send Expect: 100-continue?
306 public boolean isUsing100() {
311 * Can we wait to receive a delete file call before deleting file
313 public boolean isPrivilegedSubscriber() {
314 return (privilegedSubscriber);
319 * Raw configuration entry for controlled ingress to the data router node
321 public static class ProvForceIngress {
323 private String feedid;
324 private String subnet;
326 private String[] nodes;
329 * Construct a forced ingress configuration entry
331 * @param feedid The feed ID that this entry applies to
332 * @param subnet The CIDR for which publisher IP addresses this entry applies to or "" if it applies to all
333 * publisher IP addresses
334 * @param user The publishing user this entry applies to or "" if it applies to all publishing users.
335 * @param nodes The array of FQDNs of the data router nodes to redirect publication attempts to.
337 public ProvForceIngress(String feedid, String subnet, String user, String[] nodes) {
338 this.feedid = feedid;
339 this.subnet = subnet;
347 public String getFeedId() {
354 public String getSubnet() {
361 public String getUser() {
368 public String[] getNodes() {
374 * Raw configuration entry for controlled egress from the data router
376 public static class ProvForceEgress {
378 private String subid;
382 * Construct a forced egress configuration entry
384 * @param subid The subscription ID the subscription with forced egress
385 * @param node The node handling deliveries for this subscription
387 public ProvForceEgress(String subid, String node) {
393 * Get the subscription ID
395 public String getSubId() {
402 public String getNode() {
408 * Raw configuration entry for routing within the data router network
410 public static class ProvHop {
417 * A human readable description of this entry
419 public String toString() {
420 return ("Hop " + from + "->" + to + " via " + via);
424 * Construct a hop entry
426 * @param from The FQDN of the node with the data to be delivered
427 * @param to The FQDN of the node that will deliver to the subscriber
428 * @param via The FQDN of the node where the from node should send the data
430 public ProvHop(String from, String to, String via) {
439 public String getFrom() {
446 public String getTo() {
451 * Get the next intermediate node
453 public String getVia() {
458 private static class Redirection {
465 private static class Feed {
469 SubnetMatcher[] subnets;
470 Hashtable<String, String> authusers = new Hashtable<String, String>();
471 Redirection[] redirections;
475 private Hashtable<String, String> params = new Hashtable<>();
476 private Hashtable<String, Feed> feeds = new Hashtable<>();
477 private Hashtable<String, DestInfo> nodeinfo = new Hashtable<>();
478 private Hashtable<String, DestInfo> subinfo = new Hashtable<>();
479 private Hashtable<String, IsFrom> nodes = new Hashtable<>();
480 private Hashtable<String, ProvSubscription> provSubscriptions = new Hashtable<>();
481 private String myname;
482 private String myauth;
483 private DestInfo[] alldests;
487 * Process the raw provisioning data to configure this node
489 * @param pd The parsed provisioning data
490 * @param myname My name as seen by external systems
491 * @param spooldir The directory where temporary files live
492 * @param port The port number for URLs
493 * @param nodeauthkey The keying string used to generate node authentication credentials
495 public NodeConfig(ProvData pd, String myname, String spooldir, int port, String nodeauthkey) {
496 this.myname = myname;
497 for (ProvParam p : pd.getParams()) {
498 params.put(p.getName(), p.getValue());
500 Vector<DestInfo> destInfos = new Vector<>();
501 myauth = NodeUtils.getNodeAuthHdr(myname, nodeauthkey);
502 for (ProvNode pn : pd.getNodes()) {
503 String cn = pn.getCName();
504 if (nodeinfo.get(cn) != null) {
507 String auth = NodeUtils.getNodeAuthHdr(cn, nodeauthkey);
508 DestInfo di = new DestInfo("n:" + cn, spooldir + "/n/" + cn, null, "n2n-" + cn,
509 "https://" + cn + ":" + port + "/internal/publish", cn, myauth, false, true, false);
510 (new File(di.getSpool())).mkdirs();
512 nodeinfo.put(cn, di);
513 nodes.put(auth, new IsFrom(cn));
515 PathFinder pf = new PathFinder(myname, nodeinfo.keySet().toArray(new String[nodeinfo.size()]), pd.getHops());
516 Hashtable<String, Vector<Redirection>> rdtab = new Hashtable<String, Vector<Redirection>>();
517 for (ProvForceIngress pfi : pd.getForceIngress()) {
518 Vector<Redirection> v = rdtab.get(pfi.getFeedId());
520 v = new Vector<Redirection>();
521 rdtab.put(pfi.getFeedId(), v);
523 Redirection r = new Redirection();
524 if (pfi.getSubnet() != null) {
525 r.snm = new SubnetMatcher(pfi.getSubnet());
527 r.user = pfi.getUser();
528 r.nodes = pfi.getNodes();
531 Hashtable<String, Hashtable<String, String>> pfutab = new Hashtable<String, Hashtable<String, String>>();
532 for (ProvFeedUser pfu : pd.getFeedUsers()) {
533 Hashtable<String, String> t = pfutab.get(pfu.getFeedId());
535 t = new Hashtable<String, String>();
536 pfutab.put(pfu.getFeedId(), t);
538 t.put(pfu.getCredentials(), pfu.getUser());
540 Hashtable<String, String> egrtab = new Hashtable<String, String>();
541 for (ProvForceEgress pfe : pd.getForceEgress()) {
542 if (pfe.getNode().equals(myname) || nodeinfo.get(pfe.getNode()) == null) {
545 egrtab.put(pfe.getSubId(), pfe.getNode());
547 Hashtable<String, Vector<SubnetMatcher>> pfstab = new Hashtable<>();
548 for (ProvFeedSubnet pfs : pd.getFeedSubnets()) {
549 Vector<SubnetMatcher> v = pfstab.get(pfs.getFeedId());
551 v = new Vector<SubnetMatcher>();
552 pfstab.put(pfs.getFeedId(), v);
554 v.add(new SubnetMatcher(pfs.getCidr()));
556 Hashtable<String, StringBuffer> feedTargets = new Hashtable<>();
557 HashSet<String> allfeeds = new HashSet<>();
558 for (ProvFeed pfx : pd.getFeeds()) {
559 if (pfx.getStatus() == null) {
560 allfeeds.add(pfx.getId());
563 for (ProvSubscription provSubscription : pd.getSubscriptions()) {
564 String subId = provSubscription.getSubId();
565 String feedId = provSubscription.getFeedId();
566 if (!allfeeds.contains(feedId)) {
569 if (subinfo.get(subId) != null) {
574 sididx = Integer.parseInt(subId);
575 sididx -= sididx % 100;
576 } catch (Exception e) {
578 String subscriptionDirectory = sididx + "/" + subId;
579 DestInfo destinationInfo = new DestInfo("s:" + subId,
580 spooldir + "/s/" + subscriptionDirectory, provSubscription);
581 (new File(destinationInfo.getSpool())).mkdirs();
582 destInfos.add(destinationInfo);
583 provSubscriptions.put(subId, provSubscription);
584 subinfo.put(subId, destinationInfo);
585 String egr = egrtab.get(subId);
587 subId = pf.getPath(egr) + subId;
589 StringBuffer sb = feedTargets.get(feedId);
591 sb = new StringBuffer();
592 feedTargets.put(feedId, sb);
594 sb.append(' ').append(subId);
596 alldests = destInfos.toArray(new DestInfo[destInfos.size()]);
597 for (ProvFeed pfx : pd.getFeeds()) {
598 String fid = pfx.getId();
599 Feed f = feeds.get(fid);
605 f.loginfo = pfx.getLogData();
606 f.status = pfx.getStatus();
607 Vector<SubnetMatcher> v1 = pfstab.get(fid);
609 f.subnets = new SubnetMatcher[0];
611 f.subnets = v1.toArray(new SubnetMatcher[v1.size()]);
613 Hashtable<String, String> h1 = pfutab.get(fid);
615 h1 = new Hashtable<String, String>();
618 Vector<Redirection> v2 = rdtab.get(fid);
620 f.redirections = new Redirection[0];
622 f.redirections = v2.toArray(new Redirection[v2.size()]);
624 StringBuffer sb = feedTargets.get(fid);
626 f.targets = new Target[0];
628 f.targets = parseRouting(sb.toString());
634 * Parse a target string into an array of targets
636 * @param routing Target string
637 * @return Array of targets.
639 public Target[] parseRouting(String routing) {
640 routing = routing.trim();
641 if ("".equals(routing)) {
642 return (new Target[0]);
644 String[] xx = routing.split("\\s+");
645 Hashtable<String, Target> tmap = new Hashtable<String, Target>();
646 HashSet<String> subset = new HashSet<String>();
647 Vector<Target> tv = new Vector<Target>();
648 Target[] ret = new Target[xx.length];
649 for (int i = 0; i < xx.length; i++) {
651 int j = t.indexOf('/');
653 DestInfo di = subinfo.get(t);
655 tv.add(new Target(null, t));
657 if (!subset.contains(t)) {
659 tv.add(new Target(di, null));
663 String node = t.substring(0, j);
664 String rtg = t.substring(j + 1);
665 DestInfo di = nodeinfo.get(node);
667 tv.add(new Target(null, t));
669 Target tt = tmap.get(node);
671 tt = new Target(di, rtg);
680 return (tv.toArray(new Target[tv.size()]));
684 * Check whether this is a valid node-to-node transfer
686 * @param credentials Credentials offered by the supposed node
687 * @param ip IP address the request came from
689 public boolean isAnotherNode(String credentials, String ip) {
690 IsFrom n = nodes.get(credentials);
691 return (n != null && n.isFrom(ip));
695 * Check whether publication is allowed.
697 * @param feedid The ID of the feed being requested.
698 * @param credentials The offered credentials
699 * @param ip The requesting IP address
701 public String isPublishPermitted(String feedid, String credentials, String ip) {
702 Feed f = feeds.get(feedid);
703 String nf = "Feed does not exist";
710 String user = f.authusers.get(credentials);
712 return ("Publisher not permitted for this feed");
714 if (f.subnets.length == 0) {
717 byte[] addr = NodeUtils.getInetAddress(ip);
718 for (SubnetMatcher snm : f.subnets) {
719 if (snm.matches(addr)) {
723 return ("Publisher not permitted for this feed");
727 * Check whether delete file is allowed.
729 * @param subId The ID of the subscription being requested.
731 public boolean isDeletePermitted(String subId) {
732 ProvSubscription provSubscription = provSubscriptions.get(subId);
733 return provSubscription.isPrivilegedSubscriber();
737 * Get authenticated user
739 public String getAuthUser(String feedid, String credentials) {
740 return (feeds.get(feedid).authusers.get(credentials));
744 * Check if the request should be redirected to a different ingress node
746 public String getIngressNode(String feedid, String user, String ip) {
747 Feed f = feeds.get(feedid);
748 if (f.redirections.length == 0) {
751 byte[] addr = NodeUtils.getInetAddress(ip);
752 for (Redirection r : f.redirections) {
753 if (r.user != null && !user.equals(r.user)) {
756 if (r.snm != null && !r.snm.matches(addr)) {
759 for (String n : r.nodes) {
760 if (myname.equals(n)) {
764 if (r.nodes.length == 0) {
767 return (r.nodes[rrcntr++ % r.nodes.length]);
773 * Get a provisioned configuration parameter
775 public String getProvParam(String name) {
776 return (params.get(name));
780 * Get all the DestInfos
782 public DestInfo[] getAllDests() {
787 * Get the targets for a feed
789 * @param feedid The feed ID
790 * @return The targets this feed should be delivered to
792 public Target[] getTargets(String feedid) {
793 if (feedid == null) {
794 return (new Target[0]);
796 Feed f = feeds.get(feedid);
798 return (new Target[0]);
804 * Get the feed ID for a subscription
806 * @param subid The subscription ID
807 * @return The feed ID
809 public String getFeedId(String subid) {
810 DestInfo di = subinfo.get(subid);
814 return (di.getLogData());
818 * Get the spool directory for a subscription
820 * @param subid The subscription ID
821 * @return The spool directory
823 public String getSpoolDir(String subid) {
824 DestInfo di = subinfo.get(subid);
828 return (di.getSpool());
832 * Get the Authorization value this node uses
834 * @return The Authorization header value for this node
836 public String getMyAuth() {