- Increase the security of "shutdownWorker" and "cancelShutdownWorker" endpoints, by only allowing the requests, which come from the same machine.
- Update the "UriBuilder.java" to be able to take the running port of the server, in case the port-number was initially set to "random" (0).
This commit is contained in:
parent
25070d7aba
commit
d73a99b1c0
|
@ -13,6 +13,7 @@ import org.springframework.boot.CommandLineRunner;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
@ -109,9 +110,9 @@ public class UrlsWorkerApplication {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public CommandLineRunner setServerBaseUrl(Environment environment)
|
public CommandLineRunner setServerBaseUrl(Environment environment, ServletWebServerApplicationContext webServerAppCtxt)
|
||||||
{
|
{
|
||||||
return args -> new UriBuilder(environment);
|
return args -> new UriBuilder(environment, webServerAppCtxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package eu.openaire.urls_worker.controllers;
|
package eu.openaire.urls_worker.controllers;
|
||||||
|
|
||||||
import eu.openaire.urls_worker.UrlsWorkerApplication;
|
import eu.openaire.urls_worker.UrlsWorkerApplication;
|
||||||
|
import eu.openaire.urls_worker.util.UriBuilder;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
@ -10,6 +11,7 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -35,34 +37,32 @@ public class GeneralController {
|
||||||
public static boolean shouldShutdownWorker = false;
|
public static boolean shouldShutdownWorker = false;
|
||||||
|
|
||||||
@GetMapping("shutdownWorker/{shutdownCode}")
|
@GetMapping("shutdownWorker/{shutdownCode}")
|
||||||
public ResponseEntity<?> shutdownWorkerGracefully(@PathVariable String shutdownCode)
|
public ResponseEntity<?> shutdownWorkerGracefully(@PathVariable String shutdownCode, HttpServletRequest request)
|
||||||
{
|
{
|
||||||
String initMsg = "Received a \"shutdownWorker\" request.";
|
String initMsg = "Received a \"shutdownWorker\" request.";
|
||||||
if ( shutdownCode.equals(UrlsWorkerApplication.shutdownOrCancelCode) ) {
|
|
||||||
shouldShutdownWorker = true;
|
ResponseEntity<?> responseEntity = passSecurityChecks(request, shutdownCode, initMsg);
|
||||||
logger.info(initMsg + " The worker will shutdown, after finishing current work.");
|
if ( responseEntity != null )
|
||||||
return ResponseEntity.ok().build();
|
return responseEntity;
|
||||||
} else {
|
|
||||||
String errorMsg = initMsg + " But, it contains an invalid \"shutdownCode\": " + shutdownCode;
|
shouldShutdownWorker = true;
|
||||||
logger.error(errorMsg);
|
logger.info(initMsg + " The worker will shutdown, after finishing current work.");
|
||||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(errorMsg);
|
return ResponseEntity.ok().build();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@GetMapping("cancelShutdownWorker/{cancelCode}")
|
@GetMapping("cancelShutdownWorker/{cancelCode}")
|
||||||
public ResponseEntity<?> cancelShutdownWorkerGracefully(@PathVariable String cancelCode)
|
public ResponseEntity<?> cancelShutdownWorkerGracefully(@PathVariable String cancelCode, HttpServletRequest request)
|
||||||
{
|
{
|
||||||
String initMsg = "Received a \"cancelShutdownWorker\" request.";
|
String initMsg = "Received a \"cancelShutdownWorker\" request.";
|
||||||
if ( cancelCode.equals(UrlsWorkerApplication.shutdownOrCancelCode) ) {
|
|
||||||
shouldShutdownWorker = false;
|
ResponseEntity<?> responseEntity = passSecurityChecks(request, cancelCode, initMsg);
|
||||||
logger.info(initMsg + " Any previous \"shutdownWorker\"-request is canceled. The \"maxAssignmentsBatchesToHandleBeforeShutdown\" will still be honored (if it's set).");
|
if ( responseEntity != null )
|
||||||
return ResponseEntity.ok().build();
|
return responseEntity;
|
||||||
} else {
|
|
||||||
String errorMsg = initMsg + " But, it contains an invalid \"cancelCode\": " + cancelCode;
|
shouldShutdownWorker = false;
|
||||||
logger.error(errorMsg);
|
logger.info(initMsg + " Any previous \"shutdownWorker\"-request is canceled. The \"maxAssignmentsBatchesToHandleBeforeShutdown\" will still be honored (if it's set).");
|
||||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(errorMsg);
|
return ResponseEntity.ok().build();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,4 +78,29 @@ public class GeneralController {
|
||||||
return ResponseEntity.ok(handledAssignmentsCounts);
|
return ResponseEntity.ok(handledAssignmentsCounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static ResponseEntity<?> passSecurityChecks(HttpServletRequest request, String code, String initMsg)
|
||||||
|
{
|
||||||
|
if ( request == null ) {
|
||||||
|
logger.error(initMsg + " The \"HttpServletRequest\" is null!");
|
||||||
|
return ResponseEntity.internalServerError().build();
|
||||||
|
}
|
||||||
|
String remoteAddr = request.getHeader("X-FORWARDED-FOR");
|
||||||
|
if ( remoteAddr == null || "".equals(remoteAddr) )
|
||||||
|
remoteAddr = request.getRemoteAddr();
|
||||||
|
|
||||||
|
if ( ! (remoteAddr.equals("127.0.0.1") || remoteAddr.equals(UriBuilder.ip)) ) {
|
||||||
|
logger.error(initMsg + " The request came from another IP: " + remoteAddr + " | while this worker has the IP: " + UriBuilder.ip);
|
||||||
|
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !code.equals(UrlsWorkerApplication.shutdownOrCancelCode) ) {
|
||||||
|
String errorMsg = initMsg + " But, it contains an invalid code: " + code;
|
||||||
|
logger.error(errorMsg);
|
||||||
|
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(errorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null; // The checks are passing.
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package eu.openaire.urls_worker.util;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
@ -15,9 +16,11 @@ public class UriBuilder {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(UriBuilder.class);
|
private static final Logger logger = LoggerFactory.getLogger(UriBuilder.class);
|
||||||
|
|
||||||
|
|
||||||
|
public static String ip = null;
|
||||||
public static String baseUrl = null;
|
public static String baseUrl = null;
|
||||||
|
|
||||||
public UriBuilder(Environment environment) {
|
public UriBuilder(Environment environment, ServletWebServerApplicationContext webServerAppCtxt) {
|
||||||
baseUrl = "http";
|
baseUrl = "http";
|
||||||
|
|
||||||
String sslEnabled = environment.getProperty("server.ssl.enabled");
|
String sslEnabled = environment.getProperty("server.ssl.enabled");
|
||||||
|
@ -28,18 +31,11 @@ public class UriBuilder {
|
||||||
baseUrl += sslEnabled.equals("true") ? "s" : "";
|
baseUrl += sslEnabled.equals("true") ? "s" : "";
|
||||||
baseUrl += "://";
|
baseUrl += "://";
|
||||||
|
|
||||||
String hostName = getPublicIP();
|
ip = getPublicIP();
|
||||||
if ( hostName == null )
|
if ( ip == null )
|
||||||
hostName = InetAddress.getLoopbackAddress().getHostName(); // Non-null.
|
ip = InetAddress.getLoopbackAddress().getHostAddress(); // Non-null.
|
||||||
|
|
||||||
baseUrl += hostName;
|
baseUrl += ip + ":" + webServerAppCtxt.getWebServer().getPort();
|
||||||
|
|
||||||
String serverPort = environment.getProperty("server.port");
|
|
||||||
if (serverPort == null) { // This is unacceptable!
|
|
||||||
logger.error("No property \"server.port\" was found in \"application.properties\"!");
|
|
||||||
System.exit(-1); // Well, I guess the Spring Boot would not start in this case anyway.
|
|
||||||
}
|
|
||||||
baseUrl += ":" + serverPort;
|
|
||||||
|
|
||||||
String baseInternalPath = environment.getProperty("server.servlet.context-path");
|
String baseInternalPath = environment.getProperty("server.servlet.context-path");
|
||||||
if ( baseInternalPath != null ) {
|
if ( baseInternalPath != null ) {
|
||||||
|
|
Loading…
Reference in New Issue