X-Git-Url: https://gerrit.onap.org/r/gitweb?p=dmaap%2Fdatarouter.git;a=blobdiff_plain;f=datarouter-node%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Fdmaap%2Fdatarouter%2Fnode%2FNodeConfig.java;h=7f0182108bd6d766e21c5254b8cf4f9020fdf722;hp=d455f2d90ebb6fbeb09e39f06ef977009d6278fb;hb=0a440fd3ae3b413cd7de57677aec690f14ec7d53;hpb=3ebd2534167e73426d2b19efb05eaf9892f6f9d6 diff --git a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeConfig.java b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeConfig.java index d455f2d9..7f018210 100644 --- a/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeConfig.java +++ b/datarouter-node/src/main/java/org/onap/dmaap/datarouter/node/NodeConfig.java @@ -26,924 +26,933 @@ package org.onap.dmaap.datarouter.node; import com.att.eelf.configuration.EELFLogger; import com.att.eelf.configuration.EELFManager; - import java.io.File; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; -import java.util.Hashtable; -import java.util.Vector; /** * Processed configuration for this node. - *

- * The NodeConfig represents a processed configuration from the Data Router provisioning server. Each time + * + *

The NodeConfig represents a processed configuration from the Data Router provisioning server. Each time * configuration data is received from the provisioning server, a new NodeConfig is created and the previous one * discarded. */ public class NodeConfig { + + private static final String PUBLISHER_NOT_PERMITTED = "Publisher not permitted for this feed"; private static EELFLogger logger = EELFManager.getInstance().getLogger(NodeConfig.class); + private HashMap params = new HashMap<>(); + private HashMap feeds = new HashMap<>(); + private HashMap nodeinfo = new HashMap<>(); + private HashMap subinfo = new HashMap<>(); + private HashMap nodes = new HashMap<>(); + private HashMap provSubscriptions = new HashMap<>(); + private String myname; + private String myauth; + private DestInfo[] alldests; + private int rrcntr; + /** - * Raw configuration entry for a data router node + * Process the raw provisioning data to configure this node. + * + * @param pd The parsed provisioning data + * @param myname My name as seen by external systems + * @param spooldir The directory where temporary files live + * @param port The port number for URLs + * @param nodeauthkey The keying string used to generate node authentication credentials */ - public static class ProvNode { - - private String cname; - - /** - * Construct a node configuration entry. - * - * @param cname The cname of the node. - */ - public ProvNode(String cname) { - this.cname = cname; + public NodeConfig(ProvData pd, String myname, String spooldir, int port, String nodeauthkey) { + this.myname = myname; + for (ProvParam p : pd.getParams()) { + params.put(p.getName(), p.getValue()); } - - /** - * Get the cname of the node - */ - public String getCName() { - return (cname); + ArrayList destInfos = new ArrayList<>(); + myauth = NodeUtils.getNodeAuthHdr(myname, nodeauthkey); + for (ProvNode pn : pd.getNodes()) { + String commonName = pn.getCName(); + if (nodeinfo.get(commonName) != null) { + continue; + } + DestInfo di = new DestInfoBuilder().setName("n:" + commonName).setSpool(spooldir + "/n/" + commonName) + .setSubid(null) + .setLogdata("n2n-" + commonName).setUrl("https://" + commonName + ":" + port + "/internal/publish") + .setAuthuser(commonName).setAuthentication(myauth).setMetaonly(false).setUse100(true) + .setPrivilegedSubscriber(false).setFollowRedirects(false).setDecompress(false).createDestInfo(); + (new File(di.getSpool())).mkdirs(); + String auth = NodeUtils.getNodeAuthHdr(commonName, nodeauthkey); + destInfos.add(di); + nodeinfo.put(commonName, di); + nodes.put(auth, new IsFrom(commonName)); } - } - - /** - * Raw configuration entry for a provisioning parameter - */ - public static class ProvParam { - - private String name; - private String value; - - /** - * Construct a provisioning parameter configuration entry. - * - * @param name The name of the parameter. - * @param value The value of the parameter. - */ - public ProvParam(String name, String value) { - this.name = name; - this.value = value; + PathFinder pf = new PathFinder(myname, nodeinfo.keySet().toArray(new String[0]), pd.getHops()); + HashMap> rdtab = new HashMap<>(); + for (ProvForceIngress pfi : pd.getForceIngress()) { + ArrayList v = rdtab.get(pfi.getFeedId()); + if (v == null) { + v = new ArrayList<>(); + rdtab.put(pfi.getFeedId(), v); + } + Redirection r = new Redirection(); + if (pfi.getSubnet() != null) { + r.snm = new SubnetMatcher(pfi.getSubnet()); + } + r.user = pfi.getUser(); + r.nodes = pfi.getNodes(); + v.add(r); } - - /** - * Get the name of the parameter. - */ - public String getName() { - return (name); + HashMap> pfutab = new HashMap<>(); + for (ProvFeedUser pfu : pd.getFeedUsers()) { + HashMap t = pfutab.get(pfu.getFeedId()); + if (t == null) { + t = new HashMap<>(); + pfutab.put(pfu.getFeedId(), t); + } + t.put(pfu.getCredentials(), pfu.getUser()); } - - /** - * Get the value of the parameter. - */ - public String getValue() { - return (value); + HashMap egrtab = new HashMap<>(); + for (ProvForceEgress pfe : pd.getForceEgress()) { + if (pfe.getNode().equals(myname) || nodeinfo.get(pfe.getNode()) == null) { + continue; + } + egrtab.put(pfe.getSubId(), pfe.getNode()); } - } - - /** - * Raw configuration entry for a data feed. - */ - public static class ProvFeed { - - private String id; - private String logdata; - private String status; - private String createdDate; - /* - * AAF changes: TDP EPIC US# 307413 - * Passing aafInstance from to identify legacy/AAF feeds - */ - private String aafInstance; - - /** - * Construct a feed configuration entry. - * - * @param id The feed ID of the entry. - * @param logdata String for log entries about the entry. - * @param status The reason why this feed cannot be used (Feed has been deleted, Feed has been suspended) or - * null if it is valid. - */ - public ProvFeed(String id, String logdata, String status, String createdDate, String aafInstance) { - this.id = id; - this.logdata = logdata; - this.status = status; - this.createdDate = createdDate; - this.aafInstance = aafInstance; + HashMap> pfstab = new HashMap<>(); + for (ProvFeedSubnet pfs : pd.getFeedSubnets()) { + ArrayList v = pfstab.get(pfs.getFeedId()); + if (v == null) { + v = new ArrayList<>(); + pfstab.put(pfs.getFeedId(), v); + } + v.add(new SubnetMatcher(pfs.getCidr())); } - - /** - * Get the created date of the data feed. - */ - public String getCreatedDate() - { - return(createdDate); + HashMap feedTargets = new HashMap<>(); + HashSet allfeeds = new HashSet<>(); + for (ProvFeed pfx : pd.getFeeds()) { + if (pfx.getStatus() == null) { + allfeeds.add(pfx.getId()); + } } - - /** - * Get the aafInstance of the data feed. - */ - public String getAafInstance() { - return aafInstance; + for (ProvSubscription provSubscription : pd.getSubscriptions()) { + String subId = provSubscription.getSubId(); + String feedId = provSubscription.getFeedId(); + if (isFeedOrSubKnown(allfeeds, subId, feedId)) { + continue; + } + int sididx = 999; + try { + sididx = Integer.parseInt(subId); + sididx -= sididx % 100; + } catch (Exception e) { + logger.error("NODE0517 Exception NodeConfig: " + e); + } + String subscriptionDirectory = sididx + "/" + subId; + DestInfo destinationInfo = new DestInfo("s:" + subId, + spooldir + "/s/" + subscriptionDirectory, provSubscription); + (new File(destinationInfo.getSpool())).mkdirs(); + destInfos.add(destinationInfo); + provSubscriptions.put(subId, provSubscription); + subinfo.put(subId, destinationInfo); + String egr = egrtab.get(subId); + if (egr != null) { + subId = pf.getPath(egr) + subId; + } + StringBuilder sb = feedTargets.get(feedId); + if (sb == null) { + sb = new StringBuilder(); + feedTargets.put(feedId, sb); + } + sb.append(' ').append(subId); } - - /** - * Get the feed id of the data feed. - */ - public String getId() { - return (id); + alldests = destInfos.toArray(new DestInfo[0]); + for (ProvFeed pfx : pd.getFeeds()) { + String fid = pfx.getId(); + Feed f = feeds.get(fid); + if (f != null) { + continue; + } + f = new Feed(); + feeds.put(fid, f); + f.createdDate = pfx.getCreatedDate(); + f.loginfo = pfx.getLogData(); + f.status = pfx.getStatus(); + /* + * AAF changes: TDP EPIC US# 307413 + * Passing aafInstance from ProvFeed to identify legacy/AAF feeds + */ + f.aafInstance = pfx.getAafInstance(); + ArrayList v1 = pfstab.get(fid); + if (v1 == null) { + f.subnets = new SubnetMatcher[0]; + } else { + f.subnets = v1.toArray(new SubnetMatcher[0]); + } + HashMap h1 = pfutab.get(fid); + if (h1 == null) { + h1 = new HashMap(); + } + f.authusers = h1; + ArrayList v2 = rdtab.get(fid); + if (v2 == null) { + f.redirections = new Redirection[0]; + } else { + f.redirections = v2.toArray(new Redirection[0]); + } + StringBuilder sb = feedTargets.get(fid); + if (sb == null) { + f.targets = new Target[0]; + } else { + f.targets = parseRouting(sb.toString()); + } } + } - /** - * Get the log data of the data feed. - */ - public String getLogData() { - return (logdata); + /** + * Parse a target string into an array of targets + * + * @param routing Target string + * @return Array of targets. + */ + public Target[] parseRouting(String routing) { + routing = routing.trim(); + if ("".equals(routing)) { + return (new Target[0]); } - - /** - * Get the status of the data feed. - */ - public String getStatus() { - return (status); + String[] xx = routing.split("\\s+"); + HashMap tmap = new HashMap<>(); + HashSet subset = new HashSet<>(); + ArrayList tv = new ArrayList<>(); + for (int i = 0; i < xx.length; i++) { + String t = xx[i]; + int j = t.indexOf('/'); + if (j == -1) { + addTarget(subset, tv, t); + } else { + addTargetWithRouting(tmap, tv, t, j); + } } + return (tv.toArray(new Target[0])); } /** - * Raw configuration entry for a feed user. + * Check whether this is a valid node-to-node transfer + * + * @param credentials Credentials offered by the supposed node + * @param ip IP address the request came from */ - public static class ProvFeedUser { - - private String feedid; - private String user; - private String credentials; + public boolean isAnotherNode(String credentials, String ip) { + IsFrom n = nodes.get(credentials); + return (n != null && n.isFrom(ip)); + } - /** - * Construct a feed user configuration entry - * - * @param feedid The feed id. - * @param user The user that will publish to the feed. - * @param credentials The Authorization header the user will use to publish. - */ - public ProvFeedUser(String feedid, String user, String credentials) { - this.feedid = feedid; - this.user = user; - this.credentials = credentials; + /** + * Check whether publication is allowed. + * + * @param feedid The ID of the feed being requested. + * @param credentials The offered credentials + * @param ip The requesting IP address + */ + public String isPublishPermitted(String feedid, String credentials, String ip) { + Feed f = feeds.get(feedid); + String nf = "Feed does not exist"; + if (f != null) { + nf = f.status; + } + if (nf != null) { + return (nf); + } + String user = f.authusers.get(credentials); + if (user == null) { + return (PUBLISHER_NOT_PERMITTED); + } + if (f.subnets.length == 0) { + return (null); } + byte[] addr = NodeUtils.getInetAddress(ip); + for (SubnetMatcher snm : f.subnets) { + if (snm.matches(addr)) { + return (null); + } + } + return (PUBLISHER_NOT_PERMITTED); + } - /** - * Get the feed id of the feed user. - */ - public String getFeedId() { - return (feedid); + /** + * Check whether delete file is allowed. + * + * @param subId The ID of the subscription being requested. + */ + public boolean isDeletePermitted(String subId) { + ProvSubscription provSubscription = provSubscriptions.get(subId); + return provSubscription.isPrivilegedSubscriber(); + } + + /** + * Check whether publication is allowed for AAF Feed. + * + * @param feedid The ID of the feed being requested. + * @param ip The requesting IP address + */ + public String isPublishPermitted(String feedid, String ip) { + Feed f = feeds.get(feedid); + String nf = "Feed does not exist"; + if (f != null) { + nf = f.status; + } + if (nf != null) { + return nf; + } + if (f.subnets.length == 0) { + return null; + } + byte[] addr = NodeUtils.getInetAddress(ip); + for (SubnetMatcher snm : f.subnets) { + if (snm.matches(addr)) { + return null; + } } + return PUBLISHER_NOT_PERMITTED; + } - /** - * Get the user for the feed user. - */ - public String getUser() { - return (user); + /** + * Get authenticated user + */ + public String getAuthUser(String feedid, String credentials) { + return (feeds.get(feedid).authusers.get(credentials)); + } + + /** + * AAF changes: TDP EPIC US# 307413 Check AAF_instance for feed ID + * + * @param feedid The ID of the feed specified + */ + public String getAafInstance(String feedid) { + Feed f = feeds.get(feedid); + return f.aafInstance; + } + + /** + * Check if the request should be redirected to a different ingress node + */ + public String getIngressNode(String feedid, String user, String ip) { + Feed f = feeds.get(feedid); + if (f.redirections.length == 0) { + return (null); + } + byte[] addr = NodeUtils.getInetAddress(ip); + for (Redirection r : f.redirections) { + if ((r.user != null && !user.equals(r.user)) || (r.snm != null && !r.snm.matches(addr))) { + continue; + } + for (String n : r.nodes) { + if (myname.equals(n)) { + return (null); + } + } + if (r.nodes.length == 0) { + return (null); + } + return (r.nodes[rrcntr++ % r.nodes.length]); } + return (null); + } - /** - * Get the credentials for the feed user. - */ - public String getCredentials() { - return (credentials); + /** + * Get a provisioned configuration parameter + */ + public String getProvParam(String name) { + return (params.get(name)); + } + + /** + * Get all the DestInfos + */ + public DestInfo[] getAllDests() { + return (alldests); + } + + /** + * Get the targets for a feed + * + * @param feedid The feed ID + * @return The targets this feed should be delivered to + */ + public Target[] getTargets(String feedid) { + if (feedid == null) { + return (new Target[0]); + } + Feed f = feeds.get(feedid); + if (f == null) { + return (new Target[0]); } + return (f.targets); } /** - * Raw configuration entry for a feed subnet + * Get the creation date for a feed + * + * @param feedid The feed ID + * @return the timestamp of creation date of feed id passed */ - public static class ProvFeedSubnet { + public String getCreatedDate(String feedid) { + Feed f = feeds.get(feedid); + return (f.createdDate); + } - private String feedid; - private String cidr; + /** + * Get the feed ID for a subscription + * + * @param subid The subscription ID + * @return The feed ID + */ + public String getFeedId(String subid) { + DestInfo di = subinfo.get(subid); + if (di == null) { + return (null); + } + return (di.getLogData()); + } - /** - * Construct a feed subnet configuration entry - * - * @param feedid The feed ID - * @param cidr The CIDR allowed to publish to the feed. - */ - public ProvFeedSubnet(String feedid, String cidr) { - this.feedid = feedid; - this.cidr = cidr; + /** + * Get the spool directory for a subscription + * + * @param subid The subscription ID + * @return The spool directory + */ + public String getSpoolDir(String subid) { + DestInfo di = subinfo.get(subid); + if (di == null) { + return (null); + } + return (di.getSpool()); + } + + /** + * Get the Authorization value this node uses + * + * @return The Authorization header value for this node + */ + public String getMyAuth() { + return (myauth); + } + + private boolean isFeedOrSubKnown(HashSet allfeeds, String subId, String feedId) { + return !allfeeds.contains(feedId) || subinfo.get(subId) != null; + } + + private void addTargetWithRouting(HashMap tmap, ArrayList tv, String t, int j) { + String node = t.substring(0, j); + String rtg = t.substring(j + 1); + DestInfo di = nodeinfo.get(node); + if (di == null) { + tv.add(new Target(null, t)); + } else { + Target tt = tmap.get(node); + if (tt == null) { + tt = new Target(di, rtg); + tmap.put(node, tt); + tv.add(tt); + } else { + tt.addRouting(rtg); + } + } + } + + private void addTarget(HashSet subset, ArrayList tv, String t) { + DestInfo di = subinfo.get(t); + if (di == null) { + tv.add(new Target(null, t)); + } else { + if (!subset.contains(t)) { + subset.add(t); + tv.add(new Target(di, null)); + } } + } + + /** + * Raw configuration entry for a data router node + */ + public static class ProvNode { + + private String cname; /** - * Get the feed id of the feed subnet. + * Construct a node configuration entry. + * + * @param cname The cname of the node. */ - public String getFeedId() { - return (feedid); + public ProvNode(String cname) { + this.cname = cname; } /** - * Get the CIDR of the feed subnet. + * Get the cname of the node */ - public String getCidr() { - return (cidr); + public String getCName() { + return (cname); } } /** - * Raw configuration entry for a subscription + * Raw configuration entry for a provisioning parameter */ - public static class ProvSubscription { + public static class ProvParam { - private String subid; - private String feedid; - private String url; - private String authuser; - private String credentials; - private boolean metaonly; - private boolean use100; - private boolean privilegedSubscriber; - private boolean followRedirect; - private boolean decompress; + private String name; + private String value; /** - * Construct a subscription configuration entry + * Construct a provisioning parameter configuration entry. * - * @param subid The subscription ID - * @param feedid The feed ID - * @param url The base delivery URL (not including the fileid) - * @param authuser The user in the credentials used to deliver - * @param credentials The credentials used to authenticate to the delivery URL exactly as they go in the - * Authorization header. - * @param metaonly Is this a meta data only subscription? - * @param use100 Should we send Expect: 100-continue? - * @param privilegedSubscriber Can we wait to receive a delete file call before deleting file - * @param followRedirect Is follow redirect of destination enabled? - * @param decompress To see if they want their information compressed or decompressed + * @param name The name of the parameter. + * @param value The value of the parameter. */ - public ProvSubscription(String subid, String feedid, String url, String authuser, String credentials, boolean metaonly, boolean use100, boolean privilegedSubscriber, boolean followRedirect, boolean decompress) { - this.subid = subid; - this.feedid = feedid; - this.url = url; - this.authuser = authuser; - this.credentials = credentials; - this.metaonly = metaonly; - this.use100 = use100; - this.privilegedSubscriber = privilegedSubscriber; - this.followRedirect = followRedirect; - this.decompress = decompress; + public ProvParam(String name, String value) { + this.name = name; + this.value = value; } /** - * Get the subscription ID + * Get the name of the parameter. */ - public String getSubId() { - return (subid); + public String getName() { + return (name); } /** - * Get the feed ID + * Get the value of the parameter. */ - public String getFeedId() { - return (feedid); + public String getValue() { + return (value); } + } - /** - * Get the delivery URL - */ - public String getURL() { - return (url); - } + /** + * Raw configuration entry for a data feed. + */ + public static class ProvFeed { - /** - * Get the user + private String id; + private String logdata; + private String status; + private String createdDate; + /* + * AAF changes: TDP EPIC US# 307413 + * Passing aafInstance from to identify legacy/AAF feeds */ - public String getAuthUser() { - return (authuser); - } + private String aafInstance; /** - * Get the delivery credentials + * Construct a feed configuration entry. + * + * @param id The feed ID of the entry. + * @param logdata String for log entries about the entry. + * @param status The reason why this feed cannot be used (Feed has been deleted, Feed has been suspended) or + * null if it is valid. */ - public String getCredentials() { - return (credentials); + public ProvFeed(String id, String logdata, String status, String createdDate, String aafInstance) { + this.id = id; + this.logdata = logdata; + this.status = status; + this.createdDate = createdDate; + this.aafInstance = aafInstance; } /** - * Is this a meta data only subscription? + * Get the created date of the data feed. */ - public boolean isMetaDataOnly() { - return (metaonly); + public String getCreatedDate() { + return (createdDate); } /** - * Should we send Expect: 100-continue? + * Get the aafInstance of the data feed. */ - public boolean isUsing100() { - return (use100); + public String getAafInstance() { + return aafInstance; } /** - * Can we wait to receive a delete file call before deleting file + * Get the feed id of the data feed. */ - public boolean isPrivilegedSubscriber() { - return (privilegedSubscriber); + public String getId() { + return (id); } /** - * Should i decompress the file before sending it on - */ - public boolean isDecompress() { - return (decompress); + * Get the log data of the data feed. + */ + public String getLogData() { + return (logdata); } /** - * New field is added - FOLLOW_REDIRECTS feature iTrack:DATARTR-17 - 1706 - * Get the followRedirect of this destination + * Get the status of the data feed. */ - boolean getFollowRedirect() { - return(followRedirect); + public String getStatus() { + return (status); } } /** - * Raw configuration entry for controlled ingress to the data router node + * Raw configuration entry for a feed user. */ - public static class ProvForceIngress { + public static class ProvFeedUser { private String feedid; - private String subnet; private String user; - private String[] nodes; + private String credentials; /** - * Construct a forced ingress configuration entry + * Construct a feed user configuration entry * - * @param feedid The feed ID that this entry applies to - * @param subnet The CIDR for which publisher IP addresses this entry applies to or "" if it applies to all - * publisher IP addresses - * @param user The publishing user this entry applies to or "" if it applies to all publishing users. - * @param nodes The array of FQDNs of the data router nodes to redirect publication attempts to. + * @param feedid The feed id. + * @param user The user that will publish to the feed. + * @param credentials The Authorization header the user will use to publish. */ - public ProvForceIngress(String feedid, String subnet, String user, String[] nodes) { + public ProvFeedUser(String feedid, String user, String credentials) { this.feedid = feedid; - this.subnet = subnet; this.user = user; - //Sonar fix - if(nodes == null) { - this.nodes = new String[0]; - } else { - this.nodes = Arrays.copyOf(nodes, nodes.length); - } + this.credentials = credentials; } /** - * Get the feed ID + * Get the feed id of the feed user. */ public String getFeedId() { return (feedid); } /** - * Get the subnet - */ - public String getSubnet() { - return (subnet); - } - - /** - * Get the user + * Get the user for the feed user. */ public String getUser() { return (user); } /** - * Get the node + * Get the credentials for the feed user. */ - public String[] getNodes() { - return (nodes); + public String getCredentials() { + return (credentials); } } /** - * Raw configuration entry for controlled egress from the data router + * Raw configuration entry for a feed subnet */ - public static class ProvForceEgress { + public static class ProvFeedSubnet { - private String subid; - private String node; + private String feedid; + private String cidr; /** - * Construct a forced egress configuration entry + * Construct a feed subnet configuration entry * - * @param subid The subscription ID the subscription with forced egress - * @param node The node handling deliveries for this subscription + * @param feedid The feed ID + * @param cidr The CIDR allowed to publish to the feed. */ - public ProvForceEgress(String subid, String node) { - this.subid = subid; - this.node = node; + public ProvFeedSubnet(String feedid, String cidr) { + this.feedid = feedid; + this.cidr = cidr; } /** - * Get the subscription ID + * Get the feed id of the feed subnet. */ - public String getSubId() { - return (subid); + public String getFeedId() { + return (feedid); } /** - * Get the node + * Get the CIDR of the feed subnet. */ - public String getNode() { - return (node); + public String getCidr() { + return (cidr); } } /** - * Raw configuration entry for routing within the data router network + * Raw configuration entry for a subscription */ - public static class ProvHop { + public static class ProvSubscription { - private String from; - private String to; - private String via; + private String subid; + private String feedid; + private String url; + private String authuser; + private String credentials; + private boolean metaonly; + private boolean use100; + private boolean privilegedSubscriber; + private boolean followRedirect; + private boolean decompress; /** - * A human readable description of this entry + * Construct a subscription configuration entry + * + * @param subid The subscription ID + * @param feedid The feed ID + * @param url The base delivery URL (not including the fileid) + * @param authuser The user in the credentials used to deliver + * @param credentials The credentials used to authenticate to the delivery URL exactly as they go in the + * Authorization header. + * @param metaonly Is this a meta data only subscription? + * @param use100 Should we send Expect: 100-continue? + * @param privilegedSubscriber Can we wait to receive a delete file call before deleting file + * @param followRedirect Is follow redirect of destination enabled? + * @param decompress To see if they want their information compressed or decompressed */ - public String toString() { - return ("Hop " + from + "->" + to + " via " + via); + public ProvSubscription(String subid, String feedid, String url, String authuser, String credentials, + boolean metaonly, boolean use100, boolean privilegedSubscriber, boolean followRedirect, + boolean decompress) { + this.subid = subid; + this.feedid = feedid; + this.url = url; + this.authuser = authuser; + this.credentials = credentials; + this.metaonly = metaonly; + this.use100 = use100; + this.privilegedSubscriber = privilegedSubscriber; + this.followRedirect = followRedirect; + this.decompress = decompress; } /** - * Construct a hop entry - * - * @param from The FQDN of the node with the data to be delivered - * @param to The FQDN of the node that will deliver to the subscriber - * @param via The FQDN of the node where the from node should send the data + * Get the subscription ID */ - public ProvHop(String from, String to, String via) { - this.from = from; - this.to = to; - this.via = via; + public String getSubId() { + return (subid); } /** - * Get the from node + * Get the feed ID */ - public String getFrom() { - return (from); + public String getFeedId() { + return (feedid); } /** - * Get the to node + * Get the delivery URL */ - public String getTo() { - return (to); + public String getURL() { + return (url); } /** - * Get the next intermediate node + * Get the user */ - public String getVia() { - return (via); + public String getAuthUser() { + return (authuser); } - } - - private static class Redirection { - - SubnetMatcher snm; - String user; - String[] nodes; - } - - private static class Feed { - - String loginfo; - String status; - SubnetMatcher[] subnets; - Hashtable authusers = new Hashtable(); - Redirection[] redirections; - Target[] targets; - String createdDate; - String aafInstance; - } - - private Hashtable params = new Hashtable<>(); - private Hashtable feeds = new Hashtable<>(); - private Hashtable nodeinfo = new Hashtable<>(); - private Hashtable subinfo = new Hashtable<>(); - private Hashtable nodes = new Hashtable<>(); - private Hashtable provSubscriptions = new Hashtable<>(); - private String myname; - private String myauth; - private DestInfo[] alldests; - private int rrcntr; - /** - * Process the raw provisioning data to configure this node - * - * @param pd The parsed provisioning data - * @param myname My name as seen by external systems - * @param spooldir The directory where temporary files live - * @param port The port number for URLs - * @param nodeauthkey The keying string used to generate node authentication credentials - */ - public NodeConfig(ProvData pd, String myname, String spooldir, int port, String nodeauthkey) { - this.myname = myname; - for (ProvParam p : pd.getParams()) { - params.put(p.getName(), p.getValue()); - } - Vector destInfos = new Vector<>(); - myauth = NodeUtils.getNodeAuthHdr(myname, nodeauthkey); - for (ProvNode pn : pd.getNodes()) { - String cName = pn.getCName(); - if (nodeinfo.get(cName) != null) { - continue; - } - String auth = NodeUtils.getNodeAuthHdr(cName, nodeauthkey); - DestInfo di = new DestInfo.DestInfoBuilder().setName("n:" + cName).setSpool(spooldir + "/n/" + cName).setSubid(null) - .setLogdata("n2n-" + cName).setUrl("https://" + cName + ":" + port + "/internal/publish") - .setAuthuser(cName).setAuthentication(myauth).setMetaonly(false).setUse100(true) - .setPrivilegedSubscriber(false).setFollowRedirects(false).setDecompress(false).createDestInfo(); - (new File(di.getSpool())).mkdirs(); - destInfos.add(di); - nodeinfo.put(cName, di); - nodes.put(auth, new IsFrom(cName)); - } - PathFinder pf = new PathFinder(myname, nodeinfo.keySet().toArray(new String[0]), pd.getHops()); - Hashtable> rdtab = new Hashtable<>(); - for (ProvForceIngress pfi : pd.getForceIngress()) { - Vector v = rdtab.get(pfi.getFeedId()); - if (v == null) { - v = new Vector<>(); - rdtab.put(pfi.getFeedId(), v); - } - Redirection r = new Redirection(); - if (pfi.getSubnet() != null) { - r.snm = new SubnetMatcher(pfi.getSubnet()); - } - r.user = pfi.getUser(); - r.nodes = pfi.getNodes(); - v.add(r); - } - Hashtable> pfutab = new Hashtable<>(); - for (ProvFeedUser pfu : pd.getFeedUsers()) { - Hashtable t = pfutab.get(pfu.getFeedId()); - if (t == null) { - t = new Hashtable<>(); - pfutab.put(pfu.getFeedId(), t); - } - t.put(pfu.getCredentials(), pfu.getUser()); - } - Hashtable egrtab = new Hashtable<>(); - for (ProvForceEgress pfe : pd.getForceEgress()) { - if (pfe.getNode().equals(myname) || nodeinfo.get(pfe.getNode()) == null) { - continue; - } - egrtab.put(pfe.getSubId(), pfe.getNode()); - } - Hashtable> pfstab = new Hashtable<>(); - for (ProvFeedSubnet pfs : pd.getFeedSubnets()) { - Vector v = pfstab.get(pfs.getFeedId()); - if (v == null) { - v = new Vector<>(); - pfstab.put(pfs.getFeedId(), v); - } - v.add(new SubnetMatcher(pfs.getCidr())); - } - Hashtable feedTargets = new Hashtable<>(); - HashSet allfeeds = new HashSet<>(); - for (ProvFeed pfx : pd.getFeeds()) { - if (pfx.getStatus() == null) { - allfeeds.add(pfx.getId()); - } - } - for (ProvSubscription provSubscription : pd.getSubscriptions()) { - String subId = provSubscription.getSubId(); - String feedId = provSubscription.getFeedId(); - if (!allfeeds.contains(feedId)) { - continue; - } - if (subinfo.get(subId) != null) { - continue; - } - int sididx = 999; - try { - sididx = Integer.parseInt(subId); - sididx -= sididx % 100; - } catch (Exception e) { - logger.error("NODE0517 Exception NodeConfig: "+e); - } - String subscriptionDirectory = sididx + "/" + subId; - DestInfo destinationInfo = new DestInfo("s:" + subId, - spooldir + "/s/" + subscriptionDirectory, provSubscription); - (new File(destinationInfo.getSpool())).mkdirs(); - destInfos.add(destinationInfo); - provSubscriptions.put(subId, provSubscription); - subinfo.put(subId, destinationInfo); - String egr = egrtab.get(subId); - if (egr != null) { - subId = pf.getPath(egr) + subId; - } - StringBuffer sb = feedTargets.get(feedId); - if (sb == null) { - sb = new StringBuffer(); - feedTargets.put(feedId, sb); - } - sb.append(' ').append(subId); - } - alldests = destInfos.toArray(new DestInfo[0]); - for (ProvFeed pfx : pd.getFeeds()) { - String fid = pfx.getId(); - Feed f = feeds.get(fid); - if (f != null) { - continue; - } - f = new Feed(); - feeds.put(fid, f); - f.createdDate = pfx.getCreatedDate(); - f.loginfo = pfx.getLogData(); - f.status = pfx.getStatus(); - /* - * AAF changes: TDP EPIC US# 307413 - * Passing aafInstance from ProvFeed to identify legacy/AAF feeds - */ - f.aafInstance = pfx.getAafInstance(); - Vector v1 = pfstab.get(fid); - if (v1 == null) { - f.subnets = new SubnetMatcher[0]; - } else { - f.subnets = v1.toArray(new SubnetMatcher[0]); - } - Hashtable h1 = pfutab.get(fid); - if (h1 == null) { - h1 = new Hashtable(); - } - f.authusers = h1; - Vector v2 = rdtab.get(fid); - if (v2 == null) { - f.redirections = new Redirection[0]; - } else { - f.redirections = v2.toArray(new Redirection[0]); - } - StringBuffer sb = feedTargets.get(fid); - if (sb == null) { - f.targets = new Target[0]; - } else { - f.targets = parseRouting(sb.toString()); - } + /** + * Get the delivery credentials + */ + public String getCredentials() { + return (credentials); } - } - /** - * Parse a target string into an array of targets - * - * @param routing Target string - * @return Array of targets. - */ - public Target[] parseRouting(String routing) { - routing = routing.trim(); - if ("".equals(routing)) { - return (new Target[0]); - } - String[] xx = routing.split("\\s+"); - Hashtable tmap = new Hashtable(); - HashSet subset = new HashSet(); - Vector tv = new Vector(); - Target[] ret = new Target[xx.length]; - for (int i = 0; i < xx.length; i++) { - String t = xx[i]; - int j = t.indexOf('/'); - if (j == -1) { - DestInfo di = subinfo.get(t); - if (di == null) { - tv.add(new Target(null, t)); - } else { - if (!subset.contains(t)) { - subset.add(t); - tv.add(new Target(di, null)); - } - } - } else { - String node = t.substring(0, j); - String rtg = t.substring(j + 1); - DestInfo di = nodeinfo.get(node); - if (di == null) { - tv.add(new Target(null, t)); - } else { - Target tt = tmap.get(node); - if (tt == null) { - tt = new Target(di, rtg); - tmap.put(node, tt); - tv.add(tt); - } else { - tt.addRouting(rtg); - } - } - } + /** + * Is this a meta data only subscription? + */ + public boolean isMetaDataOnly() { + return (metaonly); } - return (tv.toArray(new Target[0])); - } - - /** - * Check whether this is a valid node-to-node transfer - * - * @param credentials Credentials offered by the supposed node - * @param ip IP address the request came from - */ - public boolean isAnotherNode(String credentials, String ip) { - IsFrom n = nodes.get(credentials); - return (n != null && n.isFrom(ip)); - } - /** - * Check whether publication is allowed. - * - * @param feedid The ID of the feed being requested. - * @param credentials The offered credentials - * @param ip The requesting IP address - */ - public String isPublishPermitted(String feedid, String credentials, String ip) { - Feed f = feeds.get(feedid); - String nf = "Feed does not exist"; - if (f != null) { - nf = f.status; - } - if (nf != null) { - return (nf); + /** + * Should we send Expect: 100-continue? + */ + public boolean isUsing100() { + return (use100); } - String user = f.authusers.get(credentials); - if (user == null) { - return ("Publisher not permitted for this feed"); + + /** + * Can we wait to receive a delete file call before deleting file + */ + public boolean isPrivilegedSubscriber() { + return (privilegedSubscriber); } - if (f.subnets.length == 0) { - return (null); + + /** + * Should i decompress the file before sending it on + */ + public boolean isDecompress() { + return (decompress); } - byte[] addr = NodeUtils.getInetAddress(ip); - for (SubnetMatcher snm : f.subnets) { - if (snm.matches(addr)) { - return (null); - } + + /** + * New field is added - FOLLOW_REDIRECTS feature iTrack:DATARTR-17 - 1706 Get the followRedirect of this + * destination + */ + boolean getFollowRedirect() { + return (followRedirect); } - return ("Publisher not permitted for this feed"); } /** - * Check whether delete file is allowed. - * - * @param subId The ID of the subscription being requested. + * Raw configuration entry for controlled ingress to the data router node */ - public boolean isDeletePermitted(String subId) { - ProvSubscription provSubscription = provSubscriptions.get(subId); - return provSubscription.isPrivilegedSubscriber(); - } + public static class ProvForceIngress { - /** - * Check whether publication is allowed for AAF Feed. - * @param feedid The ID of the feed being requested. - * @param ip The requesting IP address - */ - public String isPublishPermitted(String feedid, String ip) { - Feed f = feeds.get(feedid); - String nf = "Feed does not exist"; - if (f != null) { - nf = f.status; + private String feedid; + private String subnet; + private String user; + private String[] nodes; + + /** + * Construct a forced ingress configuration entry + * + * @param feedid The feed ID that this entry applies to + * @param subnet The CIDR for which publisher IP addresses this entry applies to or "" if it applies to all + * publisher IP addresses + * @param user The publishing user this entry applies to or "" if it applies to all publishing users. + * @param nodes The array of FQDNs of the data router nodes to redirect publication attempts to. + */ + public ProvForceIngress(String feedid, String subnet, String user, String[] nodes) { + this.feedid = feedid; + this.subnet = subnet; + this.user = user; + //Sonar fix + if (nodes == null) { + this.nodes = new String[0]; + } else { + this.nodes = Arrays.copyOf(nodes, nodes.length); + } } - if (nf != null) { - return(nf); + + /** + * Get the feed ID + */ + public String getFeedId() { + return (feedid); } - if (f.subnets.length == 0) { - return(null); + + /** + * Get the subnet + */ + public String getSubnet() { + return (subnet); } - byte[] addr = NodeUtils.getInetAddress(ip); - for (SubnetMatcher snm: f.subnets) { - if (snm.matches(addr)) { - return(null); - } + + /** + * Get the user + */ + public String getUser() { + return (user); } - return("Publisher not permitted for this feed"); - } - /** - * Get authenticated user - */ - public String getAuthUser(String feedid, String credentials) { - return (feeds.get(feedid).authusers.get(credentials)); + /** + * Get the node + */ + public String[] getNodes() { + return (nodes); + } } /** - * AAF changes: TDP EPIC US# 307413 - * Check AAF_instance for feed ID - * @param feedid The ID of the feed specified + * Raw configuration entry for controlled egress from the data router */ - public String getAafInstance(String feedid) { - Feed f = feeds.get(feedid); - return f.aafInstance; - } + public static class ProvForceEgress { - /** - * Check if the request should be redirected to a different ingress node - */ - public String getIngressNode(String feedid, String user, String ip) { - Feed f = feeds.get(feedid); - if (f.redirections.length == 0) { - return (null); + private String subid; + private String node; + + /** + * Construct a forced egress configuration entry + * + * @param subid The subscription ID the subscription with forced egress + * @param node The node handling deliveries for this subscription + */ + public ProvForceEgress(String subid, String node) { + this.subid = subid; + this.node = node; } - byte[] addr = NodeUtils.getInetAddress(ip); - for (Redirection r : f.redirections) { - if (r.user != null && !user.equals(r.user)) { - continue; - } - if (r.snm != null && !r.snm.matches(addr)) { - continue; - } - for (String n : r.nodes) { - if (myname.equals(n)) { - return (null); - } - } - if (r.nodes.length == 0) { - return (null); - } - return (r.nodes[rrcntr++ % r.nodes.length]); + + /** + * Get the subscription ID + */ + public String getSubId() { + return (subid); } - return (null); - } - /** - * Get a provisioned configuration parameter - */ - public String getProvParam(String name) { - return (params.get(name)); + /** + * Get the node + */ + public String getNode() { + return (node); + } } /** - * Get all the DestInfos + * Raw configuration entry for routing within the data router network */ - public DestInfo[] getAllDests() { - return (alldests); - } + public static class ProvHop { - /** - * Get the targets for a feed - * - * @param feedid The feed ID - * @return The targets this feed should be delivered to - */ - public Target[] getTargets(String feedid) { - if (feedid == null) { - return (new Target[0]); + private String from; + private String to; + private String via; + + /** + * Construct a hop entry + * + * @param from The FQDN of the node with the data to be delivered + * @param to The FQDN of the node that will deliver to the subscriber + * @param via The FQDN of the node where the from node should send the data + */ + public ProvHop(String from, String to, String via) { + this.from = from; + this.to = to; + this.via = via; } - Feed f = feeds.get(feedid); - if (f == null) { - return (new Target[0]); + + /** + * A human readable description of this entry + */ + public String toString() { + return ("Hop " + from + "->" + to + " via " + via); } - return (f.targets); - } - /** - * Get the creation date for a feed - * @param feedid The feed ID - * @return the timestamp of creation date of feed id passed - */ - public String getCreatedDate(String feedid) { - Feed f = feeds.get(feedid); - return(f.createdDate); - } + /** + * Get the from node + */ + public String getFrom() { + return (from); + } - /** - * Get the feed ID for a subscription - * - * @param subid The subscription ID - * @return The feed ID - */ - public String getFeedId(String subid) { - DestInfo di = subinfo.get(subid); - if (di == null) { - return (null); + /** + * Get the to node + */ + public String getTo() { + return (to); } - return (di.getLogData()); - } - /** - * Get the spool directory for a subscription - * - * @param subid The subscription ID - * @return The spool directory - */ - public String getSpoolDir(String subid) { - DestInfo di = subinfo.get(subid); - if (di == null) { - return (null); + /** + * Get the next intermediate node + */ + public String getVia() { + return (via); } - return (di.getSpool()); } - /** - * Get the Authorization value this node uses - * - * @return The Authorization header value for this node - */ - public String getMyAuth() { - return (myauth); + private static class Redirection { + + SubnetMatcher snm; + String user; + String[] nodes; } + private static class Feed { + + String loginfo; + String status; + SubnetMatcher[] subnets; + HashMap authusers = new HashMap<>(); + Redirection[] redirections; + Target[] targets; + String createdDate; + String aafInstance; + } }