diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java index c390f088e..b6a78ba0d 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RequestUtils.java @@ -10,6 +10,7 @@ import okhttp3.internal.http.HttpMethod; import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -20,6 +21,33 @@ public class RequestUtils { public static final String ERROR_IN_FUZZ_REQUEST_GENERATION = "Error in fuzz request generation {}"; public static final String APPLICATION_X_WWW_FORM_URLENCODED = "application/x-www-form-urlencoded"; + public static Request generateHeadRequest(FuzzRequestBean httpRequest, String endpoint) { + try { + logger.log(LogLevel.FINEST, String.format("Generate HEAD request : %s", JsonConverter.toJSON(httpRequest.getUrl())), RequestUtils.class.getName()); + StringBuilder url = new StringBuilder(endpoint); + url.append(httpRequest.getUrl()); + Request request = new Request.Builder() + .url(url.toString()) + .head() // Use HEAD to fetch only headers without the body + .build(); + return request; + } catch (Exception e) { + logger.log(LogLevel.FINEST, String.format("Error while Generating HEAD request : %s", JsonConverter.toJSON(httpRequest.getUrl())), RequestUtils.class.getName()); + } + return null; + } + + public static List refineEndpoints(FuzzRequestBean httpRequest, List endpoints) { + List refinedEndpoints = new ArrayList<>(); + for (String endpoint : endpoints) { + Request request = generateHeadRequest(httpRequest, endpoint); + if(RestClient.getInstance().isListening(request)){ + refinedEndpoints.add(endpoint); + } + } + return refinedEndpoints; + } + public static Request generateK2Request(FuzzRequestBean httpRequest, String endpoint) { try { logger.log(LogLevel.FINER, String.format("Firing request : %s", JsonConverter.toJSON(httpRequest)), RequestUtils.class.getName()); diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java index f47245526..945b1f166 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestClient.java @@ -70,7 +70,7 @@ protected OkHttpClient initialValue() { try { ConnectionPool connectionPool = new ConnectionPool(1, 5, TimeUnit.MINUTES); builder = builder.connectionPool(connectionPool); - builder = builder.callTimeout(10, TimeUnit.SECONDS); + builder = builder.callTimeout(5, TimeUnit.SECONDS); // Install the all-trusting trust manager final SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); @@ -159,6 +159,25 @@ public void fireRequest(FuzzRequestBean httpRequest, List endpoints, int } + public boolean isListening(Request request) { + if(request == null){ + return false; + } + + OkHttpClient client = clientThreadLocal.get(); + Call call = client.newCall(request); + try { + Response response = call.execute(); + if(response.isSuccessful()){ + return true; + } + } catch (IOException e) { + logger.log(LogLevel.FINER, String.format("Server is not reachable url: %s", request.url()), RestClient.class.getName()); + return false; + } + return false; + } + public int fireRequest(Request request, int repeatCount, String fuzzRequestId) throws SSLException { OkHttpClient client = clientThreadLocal.get(); @@ -202,6 +221,8 @@ public int fireRequest(Request request, int repeatCount, String fuzzRequestId) t FuzzFailEvent fuzzFailEvent = new FuzzFailEvent(AgentInfo.getInstance().getApplicationUUID()); fuzzFailEvent.setFuzzHeader(request.header(ServletHelper.CSEC_IAST_FUZZ_REQUEST_ID)); EventSendPool.getInstance().sendEvent(fuzzFailEvent); + } catch (Exception e){ + logger.log(LogLevel.FINER, String.format(CALL_FAILED_REQUEST_S_REASON, e.getMessage(), request), e, RestClient.class.getName()); } return 999; diff --git a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java index fe3cf3f7f..439e31b4c 100644 --- a/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java +++ b/newrelic-security-agent/src/main/java/com/newrelic/agent/security/instrumentator/httpclient/RestRequestProcessor.java @@ -106,10 +106,13 @@ public Boolean call() throws InterruptedException { } else { boolean postSSL = false; List endpoints = prepareAllEndpoints(NewRelicSecurity.getAgent().getApplicationConnectionConfig()); + logger.log(LogLevel.FINER, String.format("Endpoints to fire : ", endpoints), RestRequestProcessor.class.getSimpleName()); if (endpoints.isEmpty()){ endpoints = prepareAllEndpoints(httpRequest); + logger.log(LogLevel.FINER, String.format("Endpoints to fire in empty: ", endpoints), RestRequestProcessor.class.getSimpleName()); postSSL = true; } + endpoints = RequestUtils.refineEndpoints(httpRequest, endpoints); RestClient.getInstance().fireRequest(httpRequest, endpoints, repeatCount + endpoints.size() -1, controlCommand.getId()); } return true;