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;
31 * Processed configuration for this node.
33 * The NodeConfig represents a processed configuration from the Data Router
34 * provisioning server. Each time configuration data is received from the
35 * provisioning server, a new NodeConfig is created and the previous one
38 public class NodeConfig {
40 * Raw configuration entry for a data router node
42 public static class ProvNode {
46 * Construct a node configuration entry.
48 * @param cname The cname of the node.
50 public ProvNode(String cname) {
55 * Get the cname of the node
57 public String getCName() {
63 * Raw configuration entry for a provisioning parameter
65 public static class ProvParam {
70 * Construct a provisioning parameter configuration entry.
72 * @param name The name of the parameter.
73 * @param value The value of the parameter.
75 public ProvParam(String name, String value) {
81 * Get the name of the parameter.
83 public String getName() {
88 * Get the value of the parameter.
90 public String getValue() {
96 * Raw configuration entry for a data feed.
98 public static class ProvFeed {
100 private String logdata;
101 private String status;
104 * Construct a feed configuration entry.
106 * @param id The feed ID of the entry.
107 * @param logdata String for log entries about the entry.
108 * @param status The reason why this feed cannot be used (Feed has been deleted, Feed has been suspended) or null if it is valid.
110 public ProvFeed(String id, String logdata, String status) {
112 this.logdata = logdata;
113 this.status = status;
117 * Get the feed id of the data feed.
119 public String getId() {
124 * Get the log data of the data feed.
126 public String getLogData() {
131 * Get the status of the data feed.
133 public String getStatus() {
139 * Raw configuration entry for a feed user.
141 public static class ProvFeedUser {
142 private String feedid;
144 private String credentials;
147 * Construct a feed user configuration entry
149 * @param feedid The feed id.
150 * @param user The user that will publish to the feed.
151 * @param credentials The Authorization header the user will use to publish.
153 public ProvFeedUser(String feedid, String user, String credentials) {
154 this.feedid = feedid;
156 this.credentials = credentials;
160 * Get the feed id of the feed user.
162 public String getFeedId() {
167 * Get the user for the feed user.
169 public String getUser() {
174 * Get the credentials for the feed user.
176 public String getCredentials() {
177 return (credentials);
182 * Raw configuration entry for a feed subnet
184 public static class ProvFeedSubnet {
185 private String feedid;
189 * Construct a feed subnet configuration entry
191 * @param feedid The feed ID
192 * @param cidr The CIDR allowed to publish to the feed.
194 public ProvFeedSubnet(String feedid, String cidr) {
195 this.feedid = feedid;
200 * Get the feed id of the feed subnet.
202 public String getFeedId() {
207 * Get the CIDR of the feed subnet.
209 public String getCidr() {
215 * Raw configuration entry for a subscription
217 public static class ProvSubscription {
218 private String subid;
219 private String feedid;
221 private String authuser;
222 private String credentials;
223 private boolean metaonly;
224 private boolean use100;
227 * Construct a subscription configuration entry
229 * @param subid The subscription ID
230 * @param feedid The feed ID
231 * @param url The base delivery URL (not including the fileid)
232 * @param authuser The user in the credentials used to deliver
233 * @param credentials The credentials used to authenticate to the delivery URL exactly as they go in the Authorization header.
234 * @param metaonly Is this a meta data only subscription?
235 * @param use100 Should we send Expect: 100-continue?
237 public ProvSubscription(String subid, String feedid, String url, String authuser, String credentials, boolean metaonly, boolean use100) {
239 this.feedid = feedid;
241 this.authuser = authuser;
242 this.credentials = credentials;
243 this.metaonly = metaonly;
244 this.use100 = use100;
248 * Get the subscription ID
250 public String getSubId() {
257 public String getFeedId() {
262 * Get the delivery URL
264 public String getURL() {
271 public String getAuthUser() {
276 * Get the delivery credentials
278 public String getCredentials() {
279 return (credentials);
283 * Is this a meta data only subscription?
285 public boolean isMetaDataOnly() {
290 * Should we send Expect: 100-continue?
292 public boolean isUsing100() {
298 * Raw configuration entry for controlled ingress to the data router node
300 public static class ProvForceIngress {
301 private String feedid;
302 private String subnet;
304 private String[] nodes;
307 * Construct a forced ingress configuration entry
309 * @param feedid The feed ID that this entry applies to
310 * @param subnet The CIDR for which publisher IP addresses this entry applies to or "" if it applies to all publisher IP addresses
311 * @param user The publishing user this entry applies to or "" if it applies to all publishing users.
312 * @param nodes The array of FQDNs of the data router nodes to redirect publication attempts to.
314 public ProvForceIngress(String feedid, String subnet, String user, String[] nodes) {
315 this.feedid = feedid;
316 this.subnet = subnet;
324 public String getFeedId() {
331 public String getSubnet() {
338 public String getUser() {
345 public String[] getNodes() {
351 * Raw configuration entry for controlled egress from the data router
353 public static class ProvForceEgress {
354 private String subid;
358 * Construct a forced egress configuration entry
360 * @param subid The subscription ID the subscription with forced egress
361 * @param node The node handling deliveries for this subscription
363 public ProvForceEgress(String subid, String node) {
369 * Get the subscription ID
371 public String getSubId() {
378 public String getNode() {
384 * Raw configuration entry for routing within the data router network
386 public static class ProvHop {
392 * A human readable description of this entry
394 public String toString() {
395 return ("Hop " + from + "->" + to + " via " + via);
399 * Construct a hop entry
401 * @param from The FQDN of the node with the data to be delivered
402 * @param to The FQDN of the node that will deliver to the subscriber
403 * @param via The FQDN of the node where the from node should send the data
405 public ProvHop(String from, String to, String via) {
414 public String getFrom() {
421 public String getTo() {
426 * Get the next intermediate node
428 public String getVia() {
433 private static class Redirection {
434 public SubnetMatcher snm;
436 public String[] nodes;
439 private static class Feed {
440 public String loginfo;
441 public String status;
442 public SubnetMatcher[] subnets;
443 public Hashtable<String, String> authusers = new Hashtable<String, String>();
444 public Redirection[] redirections;
445 public Target[] targets;
448 private Hashtable<String, String> params = new Hashtable<String, String>();
449 private Hashtable<String, Feed> feeds = new Hashtable<String, Feed>();
450 private Hashtable<String, DestInfo> nodeinfo = new Hashtable<String, DestInfo>();
451 private Hashtable<String, DestInfo> subinfo = new Hashtable<String, DestInfo>();
452 private Hashtable<String, IsFrom> nodes = new Hashtable<String, IsFrom>();
453 private String myname;
454 private String myauth;
455 private DestInfo[] alldests;
459 * Process the raw provisioning data to configure this node
461 * @param pd The parsed provisioning data
462 * @param myname My name as seen by external systems
463 * @param spooldir The directory where temporary files live
464 * @param port The port number for URLs
465 * @param nodeauthkey The keying string used to generate node authentication credentials
467 public NodeConfig(ProvData pd, String myname, String spooldir, int port, String nodeauthkey) {
468 this.myname = myname;
469 for (ProvParam p : pd.getParams()) {
470 params.put(p.getName(), p.getValue());
472 Vector<DestInfo> div = new Vector<DestInfo>();
473 myauth = NodeUtils.getNodeAuthHdr(myname, nodeauthkey);
474 for (ProvNode pn : pd.getNodes()) {
475 String cn = pn.getCName();
476 if (nodeinfo.get(cn) != null) {
479 String auth = NodeUtils.getNodeAuthHdr(cn, nodeauthkey);
480 DestInfo di = new DestInfo("n:" + cn, spooldir + "/n/" + cn, null, "n2n-" + cn, "https://" + cn + ":" + port + "/internal/publish", cn, myauth, false, true);
481 (new File(di.getSpool())).mkdirs();
483 nodeinfo.put(cn, di);
484 nodes.put(auth, new IsFrom(cn));
486 PathFinder pf = new PathFinder(myname, nodeinfo.keySet().toArray(new String[nodeinfo.size()]), pd.getHops());
487 Hashtable<String, Vector<Redirection>> rdtab = new Hashtable<String, Vector<Redirection>>();
488 for (ProvForceIngress pfi : pd.getForceIngress()) {
489 Vector<Redirection> v = rdtab.get(pfi.getFeedId());
491 v = new Vector<Redirection>();
492 rdtab.put(pfi.getFeedId(), v);
494 Redirection r = new Redirection();
495 if (pfi.getSubnet() != null) {
496 r.snm = new SubnetMatcher(pfi.getSubnet());
498 r.user = pfi.getUser();
499 r.nodes = pfi.getNodes();
502 Hashtable<String, Hashtable<String, String>> pfutab = new Hashtable<String, Hashtable<String, String>>();
503 for (ProvFeedUser pfu : pd.getFeedUsers()) {
504 Hashtable<String, String> t = pfutab.get(pfu.getFeedId());
506 t = new Hashtable<String, String>();
507 pfutab.put(pfu.getFeedId(), t);
509 t.put(pfu.getCredentials(), pfu.getUser());
511 Hashtable<String, String> egrtab = new Hashtable<String, String>();
512 for (ProvForceEgress pfe : pd.getForceEgress()) {
513 if (pfe.getNode().equals(myname) || nodeinfo.get(pfe.getNode()) == null) {
516 egrtab.put(pfe.getSubId(), pfe.getNode());
518 Hashtable<String, Vector<SubnetMatcher>> pfstab = new Hashtable<String, Vector<SubnetMatcher>>();
519 for (ProvFeedSubnet pfs : pd.getFeedSubnets()) {
520 Vector<SubnetMatcher> v = pfstab.get(pfs.getFeedId());
522 v = new Vector<SubnetMatcher>();
523 pfstab.put(pfs.getFeedId(), v);
525 v.add(new SubnetMatcher(pfs.getCidr()));
527 Hashtable<String, StringBuffer> ttab = new Hashtable<String, StringBuffer>();
528 HashSet<String> allfeeds = new HashSet<String>();
529 for (ProvFeed pfx : pd.getFeeds()) {
530 if (pfx.getStatus() == null) {
531 allfeeds.add(pfx.getId());
534 for (ProvSubscription ps : pd.getSubscriptions()) {
535 String sid = ps.getSubId();
536 String fid = ps.getFeedId();
537 if (!allfeeds.contains(fid)) {
540 if (subinfo.get(sid) != null) {
545 sididx = Integer.parseInt(sid);
546 sididx -= sididx % 100;
547 } catch (Exception e) {
549 String siddir = sididx + "/" + sid;
550 DestInfo di = new DestInfo("s:" + sid, spooldir + "/s/" + siddir, sid, fid, ps.getURL(), ps.getAuthUser(), ps.getCredentials(), ps.isMetaDataOnly(), ps.isUsing100());
551 (new File(di.getSpool())).mkdirs();
553 subinfo.put(sid, di);
554 String egr = egrtab.get(sid);
556 sid = pf.getPath(egr) + sid;
558 StringBuffer sb = ttab.get(fid);
560 sb = new StringBuffer();
563 sb.append(' ').append(sid);
565 alldests = div.toArray(new DestInfo[div.size()]);
566 for (ProvFeed pfx : pd.getFeeds()) {
567 String fid = pfx.getId();
568 Feed f = feeds.get(fid);
574 f.loginfo = pfx.getLogData();
575 f.status = pfx.getStatus();
576 Vector<SubnetMatcher> v1 = pfstab.get(fid);
578 f.subnets = new SubnetMatcher[0];
580 f.subnets = v1.toArray(new SubnetMatcher[v1.size()]);
582 Hashtable<String, String> h1 = pfutab.get(fid);
584 h1 = new Hashtable<String, String>();
587 Vector<Redirection> v2 = rdtab.get(fid);
589 f.redirections = new Redirection[0];
591 f.redirections = v2.toArray(new Redirection[v2.size()]);
593 StringBuffer sb = ttab.get(fid);
595 f.targets = new Target[0];
597 f.targets = parseRouting(sb.toString());
603 * Parse a target string into an array of targets
605 * @param routing Target string
606 * @return Array of targets.
608 public Target[] parseRouting(String routing) {
609 routing = routing.trim();
610 if ("".equals(routing)) {
611 return (new Target[0]);
613 String[] xx = routing.split("\\s+");
614 Hashtable<String, Target> tmap = new Hashtable<String, Target>();
615 HashSet<String> subset = new HashSet<String>();
616 Vector<Target> tv = new Vector<Target>();
617 Target[] ret = new Target[xx.length];
618 for (int i = 0; i < xx.length; i++) {
620 int j = t.indexOf('/');
622 DestInfo di = subinfo.get(t);
624 tv.add(new Target(null, t));
626 if (!subset.contains(t)) {
628 tv.add(new Target(di, null));
632 String node = t.substring(0, j);
633 String rtg = t.substring(j + 1);
634 DestInfo di = nodeinfo.get(node);
636 tv.add(new Target(null, t));
638 Target tt = tmap.get(node);
640 tt = new Target(di, rtg);
649 return (tv.toArray(new Target[tv.size()]));
653 * Check whether this is a valid node-to-node transfer
655 * @param credentials Credentials offered by the supposed node
656 * @param ip IP address the request came from
658 public boolean isAnotherNode(String credentials, String ip) {
659 IsFrom n = nodes.get(credentials);
660 return (n != null && n.isFrom(ip));
664 * Check whether publication is allowed.
666 * @param feedid The ID of the feed being requested.
667 * @param credentials The offered credentials
668 * @param ip The requesting IP address
670 public String isPublishPermitted(String feedid, String credentials, String ip) {
671 Feed f = feeds.get(feedid);
672 String nf = "Feed does not exist";
679 String user = f.authusers.get(credentials);
681 return ("Publisher not permitted for this feed");
683 if (f.subnets.length == 0) {
686 byte[] addr = NodeUtils.getInetAddress(ip);
687 for (SubnetMatcher snm : f.subnets) {
688 if (snm.matches(addr)) {
692 return ("Publisher not permitted for this feed");
696 * Get authenticated user
698 public String getAuthUser(String feedid, String credentials) {
699 return (feeds.get(feedid).authusers.get(credentials));
703 * Check if the request should be redirected to a different ingress node
705 public String getIngressNode(String feedid, String user, String ip) {
706 Feed f = feeds.get(feedid);
707 if (f.redirections.length == 0) {
710 byte[] addr = NodeUtils.getInetAddress(ip);
711 for (Redirection r : f.redirections) {
712 if (r.user != null && !user.equals(r.user)) {
715 if (r.snm != null && !r.snm.matches(addr)) {
718 for (String n : r.nodes) {
719 if (myname.equals(n)) {
723 if (r.nodes.length == 0) {
726 return (r.nodes[rrcntr++ % r.nodes.length]);
732 * Get a provisioned configuration parameter
734 public String getProvParam(String name) {
735 return (params.get(name));
739 * Get all the DestInfos
741 public DestInfo[] getAllDests() {
746 * Get the targets for a feed
748 * @param feedid The feed ID
749 * @return The targets this feed should be delivered to
751 public Target[] getTargets(String feedid) {
752 if (feedid == null) {
753 return (new Target[0]);
755 Feed f = feeds.get(feedid);
757 return (new Target[0]);
763 * Get the feed ID for a subscription
765 * @param subid The subscription ID
766 * @return The feed ID
768 public String getFeedId(String subid) {
769 DestInfo di = subinfo.get(subid);
773 return (di.getLogData());
777 * Get the spool directory for a subscription
779 * @param subid The subscription ID
780 * @return The spool directory
782 public String getSpoolDir(String subid) {
783 DestInfo di = subinfo.get(subid);
787 return (di.getSpool());
791 * Get the Authorization value this node uses
793 * @return The Authorization header value for this node
795 public String getMyAuth() {