From a097ec65a10b394a639948d495ebaa7ff7bc628d Mon Sep 17 00:00:00 2001 From: Eyal Kapon Date: Wed, 11 Sep 2024 17:42:01 +0300 Subject: [PATCH] Added xsc api and receiving agent and not taking only default. --- .../jfrog/xray/client/impl/XrayClient.java | 24 ++++++++- .../xray/client/impl/XrayClientBuilder.java | 9 +++- .../client/impl/services/scan/ScanImpl.java | 24 +++++++-- .../xray/client/impl/xsc/XcsSystemClient.java | 27 ++++++++++ .../jfrog/xray/client/impl/xsc/XscClient.java | 33 ++++++++++++ .../xray/client/impl/xsc/XscEventClient.java | 33 ++++++++++++ .../xray/client/impl/xsc/XscHttpClient.java | 31 +++++++++++ .../client/impl/xsc/types/EndScanRequest.java | 52 ++++++++++++++++++ .../impl/xsc/types/ScanEventStatus.java | 25 +++++++++ .../client/impl/xsc/types/ScanEventType.java | 22 ++++++++ .../client/impl/xsc/types/ScanRequest.java | 54 +++++++++++++++++++ .../jfrog/xray/client/services/scan/Scan.java | 2 +- .../client/impl/test/EntitlementsTests.java | 2 +- .../xray/client/impl/test/SystemTests.java | 4 +- .../xray/client/impl/test/XrayTestsBase.java | 4 +- 15 files changed, 332 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/jfrog/xray/client/impl/xsc/XcsSystemClient.java create mode 100644 src/main/java/com/jfrog/xray/client/impl/xsc/XscClient.java create mode 100644 src/main/java/com/jfrog/xray/client/impl/xsc/XscEventClient.java create mode 100644 src/main/java/com/jfrog/xray/client/impl/xsc/XscHttpClient.java create mode 100644 src/main/java/com/jfrog/xray/client/impl/xsc/types/EndScanRequest.java create mode 100644 src/main/java/com/jfrog/xray/client/impl/xsc/types/ScanEventStatus.java create mode 100644 src/main/java/com/jfrog/xray/client/impl/xsc/types/ScanEventType.java create mode 100644 src/main/java/com/jfrog/xray/client/impl/xsc/types/ScanRequest.java diff --git a/src/main/java/com/jfrog/xray/client/impl/XrayClient.java b/src/main/java/com/jfrog/xray/client/impl/XrayClient.java index cc42e21..b1128d1 100644 --- a/src/main/java/com/jfrog/xray/client/impl/XrayClient.java +++ b/src/main/java/com/jfrog/xray/client/impl/XrayClient.java @@ -32,6 +32,7 @@ import org.apache.http.util.EntityUtils; import org.jfrog.build.api.util.Log; import org.jfrog.build.client.PreemptiveHttpClient; +import com.jfrog.xray.client.impl.xsc.XscClient; import java.io.IOException; import java.io.InputStream; @@ -45,16 +46,24 @@ * @author Roman Gurevitch */ public class XrayClient extends PreemptiveHttpClient implements Xray { + private XscClient xscClient; private static final ObjectMapper mapper = ObjectMapperHelper.get(); private static final String API_BASE = "/api/v1/"; - private final String baseApiUrl; private final Log log; public XrayClient(PoolingHttpClientConnectionManager connectionManager, BasicCredentialsProvider credentialsProvider, String accessToken, AuthCache authCache, HttpClientBuilder clientBuilder, int connectionRetries, Log log, String url) { super(connectionManager, credentialsProvider, accessToken, authCache, clientBuilder, connectionRetries, log); + this.baseApiUrl = URIUtil.concatUrl(url, API_BASE); this.log = log; + + + this.xscClient = new XscClient(connectionManager, credentialsProvider, accessToken, authCache, clientBuilder, connectionRetries, log, url); + } + + public XscClient getXscClient() { + return this.xscClient; } private static boolean statusNotOk(int statusCode) { @@ -114,6 +123,19 @@ public CloseableHttpResponse post(String uri, Object payload, ObjectMapper mappe return setHeadersAndExecute(postRequest); } + public CloseableHttpResponse put(String uri, Object payload) throws IOException { + return put(uri, payload, mapper); + } + + public CloseableHttpResponse put(String uri, Object payload, ObjectMapper mapper) throws IOException { + HttpPut putRequest = new HttpPut(createUrl(uri)); + byte[] body = mapper.writeValueAsBytes(payload); + log.debug("PUT" + putRequest.getURI() + "\n" + new String(body, StandardCharsets.UTF_8)); + HttpEntity requestEntity = new ByteArrayEntity(body, ContentType.APPLICATION_JSON); + putRequest.setEntity(requestEntity); + return setHeadersAndExecute(putRequest); + } + private String createUrl(String queryPath) { return URIUtil.concatUrl(baseApiUrl, queryPath); } diff --git a/src/main/java/com/jfrog/xray/client/impl/XrayClientBuilder.java b/src/main/java/com/jfrog/xray/client/impl/XrayClientBuilder.java index 1551abf..740b90f 100644 --- a/src/main/java/com/jfrog/xray/client/impl/XrayClientBuilder.java +++ b/src/main/java/com/jfrog/xray/client/impl/XrayClientBuilder.java @@ -18,9 +18,14 @@ public class XrayClientBuilder extends PreemptiveHttpClientBuilder { private String url = StringUtils.EMPTY; - public XrayClientBuilder() { + public XrayClientBuilder(String userAgent ) { + String userAgentHeader = DEFAULT_USER_AGENT; + if(userAgent != null && !userAgent.isEmpty()) { + userAgentHeader = userAgent; + } + setTimeout(CONNECTION_TIMEOUT_MILLISECONDS); - setUserAgent(DEFAULT_USER_AGENT); + setUserAgent(userAgentHeader); setLog(new NullLog()); } diff --git a/src/main/java/com/jfrog/xray/client/impl/services/scan/ScanImpl.java b/src/main/java/com/jfrog/xray/client/impl/services/scan/ScanImpl.java index 1f88849..6945dc9 100644 --- a/src/main/java/com/jfrog/xray/client/impl/services/scan/ScanImpl.java +++ b/src/main/java/com/jfrog/xray/client/impl/services/scan/ScanImpl.java @@ -47,15 +47,29 @@ public static ObjectMapper createFilteredObjectMapper() { } @Override - public GraphResponse graph(DependencyTree dependencies, XrayScanProgress progress, Runnable checkCanceled, String projectKey, String[] watches) throws IOException, InterruptedException { + public GraphResponse graph(DependencyTree dependencies, XrayScanProgress progress, Runnable checkCanceled, String projectKey, String[] watches, String msi) throws IOException, InterruptedException { + StringBuilder params = new StringBuilder(); + + if (msi != null) { + params.append("multi_scan_id=").append(msi); + } if (StringUtils.isNotBlank(projectKey)) { - return this.post("?project=" + projectKey, dependencies, progress, checkCanceled); + if (params.length() > 0) { + params.append("&"); + } + params.append("project=").append(projectKey); } + if (ArrayUtils.isNotEmpty(watches)) { - String watchesStr = "?watch=" + String.join("&watch=", watches); - return this.post(watchesStr, dependencies, progress, checkCanceled); + if (params.length() > 0) { + params.append("&"); + } + params.append("watch=").append(String.join("&watch=", watches)); } - return graph(dependencies, progress, checkCanceled); + String paramsString = params.toString(); + + return !paramsString.isEmpty() ? this.post(paramsString, dependencies, progress, checkCanceled) : graph(dependencies, progress, checkCanceled); + } @Override diff --git a/src/main/java/com/jfrog/xray/client/impl/xsc/XcsSystemClient.java b/src/main/java/com/jfrog/xray/client/impl/xsc/XcsSystemClient.java new file mode 100644 index 0000000..e401f15 --- /dev/null +++ b/src/main/java/com/jfrog/xray/client/impl/xsc/XcsSystemClient.java @@ -0,0 +1,27 @@ +package com.jfrog.xray.client.impl.xsc; + +import java.io.IOException; + +public class XcsSystemClient { + private final String SYSTEM_ENDPOINT = "/system/version"; + private final XscHttpClient httpClient; + public XcsSystemClient(XscHttpClient httpClient) { + this.httpClient = httpClient; + } + + public String getXscVersion() { + try { + String response = this.httpClient.get(SYSTEM_ENDPOINT).toString(); + return this.httpClient.extractValueFromResponse(response, "xsc_version"); + } + catch(IOException e) { + System.out.println(e.getMessage()); + return ""; + } + } + + + + + +} diff --git a/src/main/java/com/jfrog/xray/client/impl/xsc/XscClient.java b/src/main/java/com/jfrog/xray/client/impl/xsc/XscClient.java new file mode 100644 index 0000000..4d2cbbf --- /dev/null +++ b/src/main/java/com/jfrog/xray/client/impl/xsc/XscClient.java @@ -0,0 +1,33 @@ +package com.jfrog.xray.client.impl.xsc; +import org.apache.http.client.AuthCache; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.jfrog.build.api.util.Log; + +public class XscClient { + + private XscHttpClient httpClient; + private XcsSystemClient xscSystemClient; + private XscEventClient xscEventClient; + + public XscClient(PoolingHttpClientConnectionManager connectionManager, BasicCredentialsProvider credentialsProvider, String accessToken, AuthCache authCache, HttpClientBuilder clientBuilder, int connectionRetries, Log log,String url) { + this.httpClient = new XscHttpClient(connectionManager, credentialsProvider, accessToken, authCache, clientBuilder, connectionRetries, log, url); + this.xscSystemClient = new XcsSystemClient(this.httpClient); + this.xscEventClient = new XscEventClient(this.httpClient); + } + + + public XscEventClient scan(){ + return this.xscEventClient; + } + + public XcsSystemClient system(){ + return this.xscSystemClient; + } + + + + + +} diff --git a/src/main/java/com/jfrog/xray/client/impl/xsc/XscEventClient.java b/src/main/java/com/jfrog/xray/client/impl/xsc/XscEventClient.java new file mode 100644 index 0000000..714dac1 --- /dev/null +++ b/src/main/java/com/jfrog/xray/client/impl/xsc/XscEventClient.java @@ -0,0 +1,33 @@ +package com.jfrog.xray.client.impl.xsc; + +import com.jfrog.xray.client.impl.xsc.types.EndScanRequest; +import com.jfrog.xray.client.impl.xsc.types.ScanRequest; + +public class XscEventClient { + private final String EVENT_ENDPOINT = "/event"; + private final XscHttpClient httpClient; + + public XscEventClient(XscHttpClient httpClient) { + this.httpClient = httpClient; + } + + public String startScan(ScanRequest scanRequest){ + try { + String response = httpClient.post(EVENT_ENDPOINT, scanRequest).toString(); + return httpClient.extractValueFromResponse(response, "multi_scan_id"); + }catch (Exception e){ + return ""; + } + } + + public void endScan(EndScanRequest scanRequest){ + try { + httpClient.put(EVENT_ENDPOINT, scanRequest); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + + +} diff --git a/src/main/java/com/jfrog/xray/client/impl/xsc/XscHttpClient.java b/src/main/java/com/jfrog/xray/client/impl/xsc/XscHttpClient.java new file mode 100644 index 0000000..829315c --- /dev/null +++ b/src/main/java/com/jfrog/xray/client/impl/xsc/XscHttpClient.java @@ -0,0 +1,31 @@ +package com.jfrog.xray.client.impl.xsc; +import com.jfrog.xray.client.impl.XrayClient; +import org.apache.http.client.AuthCache; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.jfrog.build.api.util.Log; + + +public class XscHttpClient extends XrayClient { + private static final String XSC_BASE_URL = "/xsc/api/v1"; + + + public XscHttpClient(PoolingHttpClientConnectionManager connectionManager, BasicCredentialsProvider credentialsProvider, String accessToken, AuthCache authCache, HttpClientBuilder clientBuilder, int connectionRetries, Log log,String url) { + super(connectionManager, credentialsProvider, accessToken, authCache, clientBuilder, connectionRetries, log, url+ XSC_BASE_URL ); + } + + public String extractValueFromResponse(String json, String key) { + String searchKey = "\"" + key + "\":\""; + int startIndex = json.indexOf(searchKey); + if (startIndex == -1) { + return null; // Key not found + } + startIndex += searchKey.length(); + int endIndex = json.indexOf("\"", startIndex); + if (endIndex == -1) { + return null; + } + return json.substring(startIndex, endIndex); + } +} diff --git a/src/main/java/com/jfrog/xray/client/impl/xsc/types/EndScanRequest.java b/src/main/java/com/jfrog/xray/client/impl/xsc/types/EndScanRequest.java new file mode 100644 index 0000000..6a6ef01 --- /dev/null +++ b/src/main/java/com/jfrog/xray/client/impl/xsc/types/EndScanRequest.java @@ -0,0 +1,52 @@ +package com.jfrog.xray.client.impl.xsc.types; + +public class EndScanRequest extends ScanRequest { + private Integer totalFindings; + private Integer totalIgnoredFindings; + private Integer totalScanDuration; // Changed to String + private String multiScanId; + + public EndScanRequest( + ScanEventType eventType, + ScanEventStatus eventStatus, + String product, + String productVersion, + String jpdVersion, + String jfrogUser, + String osPlatform, + String osArchitecture, + String machineId, + String analyzerManagerVersion, + Boolean isDefaultConfig, + Integer totalFindings, + Integer totalIgnoredFindings, + Integer totalScanDuration, + String multiScanId) { + super(eventType, eventStatus, product, productVersion, jpdVersion, jfrogUser, osPlatform, osArchitecture, machineId, analyzerManagerVersion, isDefaultConfig); + this.totalScanDuration = totalScanDuration; + this.totalFindings = totalFindings; + this.totalIgnoredFindings = totalIgnoredFindings; + this.multiScanId = multiScanId; + } + + @Override + public String toString() { + return "{" + + "\"event_type\":" + this.eventType.getType() + "," + + "\"event_status\":\"" + this.eventStatus.getStatus() + "\"," + + "\"product\":\"" + this.product + "\"," + + "\"product_version\":\"" + this.productVersion + "\"," + + "\"jpd_version\":\"" + this.jpdVersion + "\"," + + "\"jfrog_user\":\"" + this.jfrogUser + "\"," + + "\"os_platform\":\"" + this.osPlatform + "\"," + + "\"os_architecture\":\"" + this.osArchitecture + "\"," + + "\"is_default_config\":" + this.isDefaultConfig + "," + + "\"machine_id\":\"" + this.machineId + "\"," + + "\"analyzer_manager_version\":\"" + this.analyzerManagerVersion + "\"," + + "\"total_findings\":" + totalFindings + "," + + "\"total_ignored_findings\":" + totalIgnoredFindings + "," + + "\"total_scan_duration\":\"" + totalScanDuration + "\"," + + "\"multi_scan_id\":\"" + multiScanId + "\"" + + "}"; + } +} \ No newline at end of file diff --git a/src/main/java/com/jfrog/xray/client/impl/xsc/types/ScanEventStatus.java b/src/main/java/com/jfrog/xray/client/impl/xsc/types/ScanEventStatus.java new file mode 100644 index 0000000..0b7779f --- /dev/null +++ b/src/main/java/com/jfrog/xray/client/impl/xsc/types/ScanEventStatus.java @@ -0,0 +1,25 @@ +package com.jfrog.xray.client.impl.xsc.types; + + +public enum ScanEventStatus { + STARTED("started"), + COMPLETED("completed"), + CANCELLED("cancelled"), + FAILED("failed"); + + private final String status; + + ScanEventStatus(String status) { + this.status = status; + } + + public String getStatus() { + return status; + } + + @Override + public String toString() { + return status; + } + +} diff --git a/src/main/java/com/jfrog/xray/client/impl/xsc/types/ScanEventType.java b/src/main/java/com/jfrog/xray/client/impl/xsc/types/ScanEventType.java new file mode 100644 index 0000000..3681c60 --- /dev/null +++ b/src/main/java/com/jfrog/xray/client/impl/xsc/types/ScanEventType.java @@ -0,0 +1,22 @@ +package com.jfrog.xray.client.impl.xsc.types; + + +public enum ScanEventType { + SOURCE_CODE(1); + + private final int type; + + ScanEventType(int type) { + this.type = type; + } + + public int getType() { + return type; + } + + @Override + public String toString() { + return Integer.toString(type); + } + +} diff --git a/src/main/java/com/jfrog/xray/client/impl/xsc/types/ScanRequest.java b/src/main/java/com/jfrog/xray/client/impl/xsc/types/ScanRequest.java new file mode 100644 index 0000000..1069ea2 --- /dev/null +++ b/src/main/java/com/jfrog/xray/client/impl/xsc/types/ScanRequest.java @@ -0,0 +1,54 @@ +package com.jfrog.xray.client.impl.xsc.types; + + + +public class ScanRequest { + + protected ScanEventType eventType; + protected ScanEventStatus eventStatus; + protected String product; + protected String productVersion; + protected String jpdVersion; + protected String jfrogUser; + protected String osPlatform; + protected String osArchitecture; + protected String machineId; + protected String analyzerManagerVersion; + protected Boolean isDefaultConfig; + + + public ScanRequest(ScanEventType eventType, ScanEventStatus eventStatus, String product, + String productVersion, String jpdVersion, String jfrogUser, + String osPlatform, String osArchitecture, String machineId, + String analyzerManagerVersion, Boolean isDefaultConfig) { + this.eventType = eventType; + this.eventStatus = eventStatus; + this.product = product; + this.productVersion = productVersion; + this.jpdVersion = jpdVersion; + this.jfrogUser = jfrogUser; + this.osPlatform = osPlatform; + this.osArchitecture = osArchitecture; + this.machineId = machineId; + this.analyzerManagerVersion = analyzerManagerVersion; + this.isDefaultConfig = isDefaultConfig; + } + + + @Override + public String toString() { + return "{" + + "\"event_type\":" + this.eventType.getType() + "," + + "\"event_status\":\"" + this.eventStatus.getStatus() + "\"," + + "\"product\":\"" + this.product + "\"," + + "\"product_version\":\"" + this.productVersion + "\"," + + "\"jpd_version\":\"" + this.jpdVersion + "\"," + + "\"jfrog_user\":\"" + this.jfrogUser + "\"," + + "\"os_platform\":\"" + this.osPlatform + "\"," + + "\"os_architecture\":\"" + this.osArchitecture + "\"," + + "\"is_default_config\":" + this.isDefaultConfig + "," + + "\"machine_id\":\"" + this.machineId + "\"," + + "\"analyzer_manager_version\":\"" + this.analyzerManagerVersion + "\"" + + "}"; + } +} diff --git a/src/main/java/com/jfrog/xray/client/services/scan/Scan.java b/src/main/java/com/jfrog/xray/client/services/scan/Scan.java index 1bd37fd..6e28539 100644 --- a/src/main/java/com/jfrog/xray/client/services/scan/Scan.java +++ b/src/main/java/com/jfrog/xray/client/services/scan/Scan.java @@ -11,7 +11,7 @@ */ public interface Scan extends Serializable { - GraphResponse graph(DependencyTree dependencies, XrayScanProgress progress, Runnable checkCanceled, String projectKey, String[] watches) throws IOException, InterruptedException; + GraphResponse graph(DependencyTree dependencies, XrayScanProgress progress, Runnable checkCanceled, String projectKey, String[] watches, String msi) throws IOException, InterruptedException; GraphResponse graph(DependencyTree dependencies, XrayScanProgress progress, Runnable checkCanceled) throws IOException, InterruptedException; } diff --git a/src/test/java/com/jfrog/xray/client/impl/test/EntitlementsTests.java b/src/test/java/com/jfrog/xray/client/impl/test/EntitlementsTests.java index 674762a..2423fbf 100644 --- a/src/test/java/com/jfrog/xray/client/impl/test/EntitlementsTests.java +++ b/src/test/java/com/jfrog/xray/client/impl/test/EntitlementsTests.java @@ -14,7 +14,7 @@ public class EntitlementsTests extends XrayTestsBase { @Test public void testIsEntitledParse() throws IOException { - try (Xray xrayMock = new XrayClientBuilder().setUrl("http://localhost:8888/xray/").build()) { + try (Xray xrayMock = new XrayClientBuilder(null).setUrl("http://localhost:8888/xray/").build()) { mockServer.when(request().withPath("/xray/api/v1/entitlements/feature/" + Feature.CONTEXTUAL_ANALYSIS)).respond(response().withBody("{\"entitled\":true,\"feature_id\":\"" + Feature.CONTEXTUAL_ANALYSIS + "\"}").withStatusCode(200)); assertTrue(xrayMock.entitlements().isEntitled(Feature.CONTEXTUAL_ANALYSIS)); } diff --git a/src/test/java/com/jfrog/xray/client/impl/test/SystemTests.java b/src/test/java/com/jfrog/xray/client/impl/test/SystemTests.java index 34380bf..5c29310 100644 --- a/src/test/java/com/jfrog/xray/client/impl/test/SystemTests.java +++ b/src/test/java/com/jfrog/xray/client/impl/test/SystemTests.java @@ -67,7 +67,7 @@ public void testVersionProxy() throws IOException { public void testJFrogInactiveEnv() throws IOException { mockServer.when(request().withPath("/xray/api/v1/system/version")).respond(response().withBody("{}").withStatusCode(302).withHeader(LOCATION, "http://localhost:8888/reactivate-server/eco-server")); mockServer.when(request().withPath("/reactivate-server/eco-server")).respond(response().withBody("{}").withStatusCode(200)); - try (Xray xrayMock = new XrayClientBuilder().setUrl("http://localhost:8888/xray/").build()) { + try (Xray xrayMock = new XrayClientBuilder(null).setUrl("http://localhost:8888/xray/").build()) { assertThrows(JFrogInactiveEnvironmentException.class, () -> xrayMock.system().version()); } } @@ -77,7 +77,7 @@ public void testJFrogInactiveEnvFalsePositives() throws IOException { // The redirection response doesn't contain "reactivate-server" so it should not be detected as JFrogInactiveEnv mockServer.when(request().withPath("/xray/api/v1/system/version")).respond(response().withBody("{}").withStatusCode(302).withHeader(LOCATION, "http://localhost:8888/eco-server")); mockServer.when(request().withPath("/eco-server")).respond(response().withBody("{\"xray_version\":\"3.66.4\",\"xray_revision\":\"4cae8b1\"}").withStatusCode(200)); - try (Xray xrayMock = new XrayClientBuilder().setUrl("http://localhost:8888/xray/").build()) { + try (Xray xrayMock = new XrayClientBuilder(null).setUrl("http://localhost:8888/xray/").build()) { assertEquals(xrayMock.system().version().getVersion(), "3.66.4"); } } diff --git a/src/test/java/com/jfrog/xray/client/impl/test/XrayTestsBase.java b/src/test/java/com/jfrog/xray/client/impl/test/XrayTestsBase.java index d82d4b0..59b1d6e 100644 --- a/src/test/java/com/jfrog/xray/client/impl/test/XrayTestsBase.java +++ b/src/test/java/com/jfrog/xray/client/impl/test/XrayTestsBase.java @@ -39,7 +39,7 @@ public void init() throws IOException { String accessToken = readParam(props, "token"); // Create an xray client - xray = (Xray) new XrayClientBuilder() + xray = (Xray) new XrayClientBuilder(null) .setUrl(url) .setAccessToken(accessToken) .build(); @@ -48,7 +48,7 @@ public void init() throws IOException { ProxyConfiguration proxyConfig = new ProxyConfiguration(); proxyConfig.port = 8888; proxyConfig.host = "localhost"; - xrayProxies = (Xray) new XrayClientBuilder() + xrayProxies = (Xray) new XrayClientBuilder(null) .setUrl(url) .setAccessToken(accessToken) .setProxyConfiguration(proxyConfig)