/******************************************************************************* * ============LICENSE_START================================================== * * org.onap.dmaap * * =========================================================================== * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. * * =========================================================================== * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * * ============LICENSE_END==================================================== * * * * ECOMP is a trademark and service mark of AT&T Intellectual Property. * * ******************************************************************************/ package org.onap.dmaap.datarouter.node; import com.att.eelf.configuration.EELFLogger; import com.att.eelf.configuration.EELFManager; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Writer; import java.net.Socket; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Enumeration; import java.util.regex.Pattern; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.onap.dmaap.datarouter.node.eelf.EelfMsgs; /** * Servlet for handling all http and https requests to the data router node *
* Handled requests are:
*
* GET http://node/internal/fetchProv - fetch the provisioning data
*
* PUT/DELETE https://node/internal/publish/fileid - n2n transfer
*
* PUT/DELETE https://node/publish/feedid/fileid - publsh request
*/
public class NodeServlet extends HttpServlet {
private static Logger logger = Logger.getLogger("org.onap.dmaap.datarouter.node.NodeServlet");
private static NodeConfigManager config;
private static Pattern MetaDataPattern;
private static SubnetMatcher internalsubnet = new SubnetMatcher("135.207.136.128/25");
//Adding EELF Logger Rally:US664892
private static EELFLogger eelflogger = EELFManager.getInstance()
.getLogger("org.onap.dmaap.datarouter.node.NodeServlet");
static {
try {
final String ws = "\\s*";
// assume that \\ and \" have been replaced by X
final String string = "\"[^\"]*\"";
//String string = "\"(?:[^\"\\\\]|\\\\.)*\"";
final String number = "[+-]?(?:\\.\\d+|(?:0|[1-9]\\d*)(?:\\.\\d*)?)(?:[eE][+-]?\\d+)?";
final String value = "(?:" + string + "|" + number + "|null|true|false)";
final String item = string + ws + ":" + ws + value + ws;
final String object = ws + "\\{" + ws + "(?:" + item + "(?:" + "," + ws + item + ")*)?\\}" + ws;
MetaDataPattern = Pattern.compile(object, Pattern.DOTALL);
} catch (Exception e) {
}
}
/**
* Get the NodeConfigurationManager
*/
public void init() {
config = NodeConfigManager.getInstance();
logger.info("NODE0101 Node Servlet Configured");
}
private boolean down(HttpServletResponse resp) throws IOException {
if (config.isShutdown() || !config.isConfigured()) {
resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
logger.info("NODE0102 Rejecting request: Service is being quiesced");
return (true);
}
return (false);
}
/**
* Handle a GET for /internal/fetchProv
*/
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
NodeUtils.setIpAndFqdnForEelf("doGet");
eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_FEEDID, req.getHeader("X-ATT-DR-ON-BEHALF-OF"),
getIdFromPath(req) + "");
if (down(resp)) {
return;
}
String path = req.getPathInfo();
String qs = req.getQueryString();
String ip = req.getRemoteAddr();
if (qs != null) {
path = path + "?" + qs;
}
if ("/internal/fetchProv".equals(path)) {
config.gofetch(ip);
resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
return;
} else if (path.startsWith("/internal/resetSubscription/")) {
String subid = path.substring(28);
if (subid.length() != 0 && subid.indexOf('/') == -1) {
NodeMain.resetQueue(subid, ip);
resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
return;
}
}
if (internalsubnet.matches(NodeUtils.getInetAddress(ip))) {
if (path.startsWith("/internal/logs/")) {
String f = path.substring(15);
File fn = new File(config.getLogDir() + "/" + f);
if (f.indexOf('/') != -1 || !fn.isFile()) {
logger.info("NODE0103 Rejecting invalid GET of " + path + " from " + ip);
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
byte[] buf = new byte[65536];
resp.setContentType("text/plain");
resp.setContentLength((int) fn.length());
resp.setStatus(200);
try (InputStream is = new FileInputStream(fn)) {
OutputStream os = resp.getOutputStream();
int i;
while ((i = is.read(buf)) > 0) {
os.write(buf, 0, i);
}
}
return;
}
if (path.startsWith("/internal/rtt/")) {
String xip = path.substring(14);
long st = System.currentTimeMillis();
String status = " unknown";
try {
Socket s = new Socket(xip, 443);
s.close();
status = " connected";
} catch (Exception e) {
status = " error " + e.toString();
}
long dur = System.currentTimeMillis() - st;
resp.setContentType("text/plain");
resp.setStatus(200);
byte[] buf = (dur + status + "\n").getBytes();
resp.setContentLength(buf.length);
resp.getOutputStream().write(buf);
return;
}
}
logger.info("NODE0103 Rejecting invalid GET of " + path + " from " + ip);
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
/**
* Handle all PUT requests
*/
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
NodeUtils.setIpAndFqdnForEelf("doPut");
eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_FEEDID, req.getHeader("X-ATT-DR-ON-BEHALF-OF"),
getIdFromPath(req) + "");
common(req, resp, true);
}
/**
* Handle all DELETE requests
*/
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
NodeUtils.setIpAndFqdnForEelf("doDelete");
eelflogger.info(EelfMsgs.MESSAGE_WITH_BEHALF_AND_FEEDID, req.getHeader("X-ATT-DR-ON-BEHALF-OF"),
getIdFromPath(req) + "");
common(req, resp, false);
}
private void common(HttpServletRequest req, HttpServletResponse resp, boolean isput)
throws ServletException, IOException {
if (down(resp)) {
return;
}
if (!req.isSecure()) {
logger.info(
"NODE0104 Rejecting insecure PUT or DELETE of " + req.getPathInfo() + " from " + req.getRemoteAddr());
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "https required on publish requests");
return;
}
String fileid = req.getPathInfo();
if (fileid == null) {
logger.info("NODE0105 Rejecting bad URI for PUT or DELETE of " + req.getPathInfo() + " from " + req
.getRemoteAddr());
resp.sendError(HttpServletResponse.SC_NOT_FOUND,
"Invalid request URI. Expecting