From 5032a9b50a2035ebc3bca65f92cef8a9272384bb Mon Sep 17 00:00:00 2001 From: Eyal Delarea Date: Wed, 13 Nov 2024 16:42:08 +0200 Subject: [PATCH 1/4] Promote to v1.48.0 (#1045) --- go.sum | 2 -- utils/utils.go | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/go.sum b/go.sum index f07c2363f..1461379f1 100644 --- a/go.sum +++ b/go.sum @@ -102,8 +102,6 @@ github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= diff --git a/utils/utils.go b/utils/utils.go index c4751e917..068a35eb0 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -28,7 +28,7 @@ import ( const ( Development = "development" Agent = "jfrog-client-go" - Version = "1.47.6" + Version = "1.48.0" ) const xrayDevVersion = "3.x-dev" From 50bd3e54f1e0a92759655e4689bcee89dcc8eeca Mon Sep 17 00:00:00 2001 From: Assaf Attias <49212512+attiasas@users.noreply.github.com> Date: Sun, 24 Nov 2024 19:24:51 +0200 Subject: [PATCH 2/4] Transition Xsc to Xray (#1046) --- .../services/utils/tests/xray/consts.go | 4 +- .../services/utils/tests/xray/server.go | 63 ++++++++------- tests/xrayscan_test.go | 60 -------------- xray/manager.go | 30 ++++--- xray/services/scan.go | 78 ++----------------- xray/services/xsc/xsc.go | 54 +++++++++++++ xsc/manager.go | 1 + xsc/service.go | 20 +++++ xsc/services/analytics.go | 59 ++++++++++---- xsc/services/logerrorevent.go | 29 +++++-- xsc/services/profile.go | 32 ++++++-- xsc/services/utils/utils.go | 34 ++++++++ xsc/services/utils/utils_test.go | 23 ++++++ xsc/services/version.go | 32 ++++++-- 14 files changed, 312 insertions(+), 207 deletions(-) create mode 100644 xray/services/xsc/xsc.go create mode 100644 xsc/service.go create mode 100644 xsc/services/utils/utils.go create mode 100644 xsc/services/utils/utils_test.go diff --git a/artifactory/services/utils/tests/xray/consts.go b/artifactory/services/utils/tests/xray/consts.go index 4fb0c478e..05692a839 100644 --- a/artifactory/services/utils/tests/xray/consts.go +++ b/artifactory/services/utils/tests/xray/consts.go @@ -1425,7 +1425,9 @@ const BuildScanResultsResponse = ` ] } ` -const xscVersionResponse = `{"xsc_version": "1.0.0"}` +const xscVersionResponse = `{"xsc_version": "%s","xray_version":"3.107.8"}` + +const xrayVersionResponse = `{"xray_version":"%s","xray_revision":"5735964"}` const scanIdResponse = `{"scan_id": "3472b4e2-bddc-11ee-a9c9-acde48001122"}` diff --git a/artifactory/services/utils/tests/xray/server.go b/artifactory/services/utils/tests/xray/server.go index 34b476ae4..627ebd31a 100644 --- a/artifactory/services/utils/tests/xray/server.go +++ b/artifactory/services/utils/tests/xray/server.go @@ -1,7 +1,6 @@ package xray import ( - "encoding/json" "fmt" "io" "net/http" @@ -186,10 +185,11 @@ func buildScanHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, "Invalid reports request", http.StatusBadRequest) } -func xscGetVersionHandlerFunc(t *testing.T) func(w http.ResponseWriter, r *http.Request) { +func xscGetVersionHandlerFunc(t *testing.T, version string) func(w http.ResponseWriter, r *http.Request) { + expectedResponse := fmt.Sprintf(xscVersionResponse, version) return func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodGet { - _, err := fmt.Fprint(w, xscVersionResponse) + _, err := fmt.Fprint(w, expectedResponse) assert.NoError(t, err) return } @@ -197,6 +197,18 @@ func xscGetVersionHandlerFunc(t *testing.T) func(w http.ResponseWriter, r *http. } } +func xrayGetVersionHandlerFunc(t *testing.T, version string) func(w http.ResponseWriter, r *http.Request) { + expectedResponse := fmt.Sprintf(xrayVersionResponse, version) + return func(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodGet { + _, err := fmt.Fprint(w, expectedResponse) + assert.NoError(t, err) + return + } + http.Error(w, "Invalid xray request", http.StatusBadRequest) + } +} + func enrichGetScanId(t *testing.T) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost { @@ -230,43 +242,34 @@ func enrichGetResults(t *testing.T) func(w http.ResponseWriter, r *http.Request) } } -func xscGitInfoHandlerFunc(t *testing.T) func(w http.ResponseWriter, r *http.Request) { - return func(w http.ResponseWriter, r *http.Request) { - req, err := io.ReadAll(r.Body) - assert.NoError(t, err) - if r.Method == http.MethodPost { - var reqBody services.XscGitInfoContext - err = json.Unmarshal(req, &reqBody) - assert.NoError(t, err) - if reqBody.GitRepoUrl == "" || reqBody.BranchName == "" || reqBody.CommitHash == "" { - w.WriteHeader(http.StatusBadRequest) - _, err := fmt.Fprint(w, XscGitInfoBadResponse) - assert.NoError(t, err) - return - } - w.WriteHeader(http.StatusCreated) - _, err = fmt.Fprint(w, XscGitInfoResponse) - assert.NoError(t, err) - return - } - http.Error(w, "Invalid xsc request", http.StatusBadRequest) - } +type MockServerParams struct { + MSI string + XrayVersion string + XscVersion string } func StartXrayMockServer(t *testing.T) int { + params := MockServerParams{MSI: TestMultiScanId, XrayVersion: "3.0.0", XscVersion: "1.0.0"} + return StartXrayMockServerWithParams(t, params) +} + +func StartXrayMockServerWithParams(t *testing.T, params MockServerParams) int { handlers := clienttests.HttpServerHandlers{} + + handlers["/"] = http.NotFound + // Xray handlers + handlers["/xray/api/v1/system/version"] = xrayGetVersionHandlerFunc(t, params.XrayVersion) handlers["/api/xray/scanBuild"] = scanBuildHandler handlers["/api/v2/summary/artifact"] = artifactSummaryHandler handlers["/api/v1/entitlements/feature/"] = entitlementsHandler - handlers["/xsc/api/v1/system/version"] = xscGetVersionHandlerFunc(t) - handlers["/xsc/api/v1/gitinfo"] = xscGitInfoHandlerFunc(t) handlers["/xray/api/v1/scan/import_xml"] = enrichGetScanId(t) + handlers[fmt.Sprintf("/xray/api/v1/scan/graph/%s", params.MSI)] = enrichGetResults(t) handlers["/xray/api/v1/configuration/jas"] = getJasConfig(t) - getEnrichResults := fmt.Sprintf("/xray/api/v1/scan/graph/%s", TestMultiScanId) - handlers[getEnrichResults] = enrichGetResults(t) - handlers[fmt.Sprintf("/%s/", services.ReportsAPI)] = reportHandler handlers[fmt.Sprintf("/%s/", services.BuildScanAPI)] = buildScanHandler - handlers["/"] = http.NotFound + handlers[fmt.Sprintf("/%s/", services.ReportsAPI)] = reportHandler + // Xsc handlers + handlers["/xsc/api/v1/system/version"] = xscGetVersionHandlerFunc(t, params.XscVersion) + handlers["/xray/api/v1/xsc/system/version"] = xscGetVersionHandlerFunc(t, params.XscVersion) port, err := clienttests.StartHttpServer(handlers) if err != nil { diff --git a/tests/xrayscan_test.go b/tests/xrayscan_test.go index d031c25fb..5cb75d95e 100644 --- a/tests/xrayscan_test.go +++ b/tests/xrayscan_test.go @@ -1,8 +1,6 @@ package tests import ( - "github.com/jfrog/jfrog-client-go/auth" - "github.com/stretchr/testify/assert" "strconv" "strings" "testing" @@ -10,11 +8,9 @@ import ( "github.com/jfrog/jfrog-client-go/artifactory/services" "github.com/jfrog/jfrog-client-go/artifactory/services/utils/tests/xray" "github.com/jfrog/jfrog-client-go/http/jfroghttpclient" - xrayServices "github.com/jfrog/jfrog-client-go/xray/services" ) var testsXrayScanService *services.XrayScanService -var testsScanService *xrayServices.ScanService func TestNewXrayScanService(t *testing.T) { initXrayTest(t) @@ -64,59 +60,3 @@ func scanBuild(t *testing.T, buildName, buildNumber, expected string) { t.Error("Expected:", expected, "Got: ", string(result)) } } - -func TestIsXscEnabled(t *testing.T) { - xrayServerPort, xrayDetails, client := initXrayScanTest(t) - testsScanService = xrayServices.NewScanService(client) - testsScanService.XrayDetails = xrayDetails - testsScanService.XrayDetails.SetUrl("http://localhost:" + strconv.Itoa(xrayServerPort) + "/xray/") - - result, err := testsScanService.IsXscEnabled() - assert.NoError(t, err) - assert.Equal(t, xray.TestXscVersion, result) -} - -func TestSendScanGitInfoContext(t *testing.T) { - xrayServerPort, xrayDetails, client := initXrayScanTest(t) - testsScanService = xrayServices.NewScanService(client) - testsScanService.XrayDetails = xrayDetails - testsScanService.XrayDetails.SetUrl("http://localhost:" + strconv.Itoa(xrayServerPort) + "/xray/") - - // Run tests - tests := []struct { - name string - gitInfoContext *xrayServices.XscGitInfoContext - expected string - }{ - {name: "ValidGitInfoContext", gitInfoContext: &xray.GitInfoContextWithMinimalRequiredFields, expected: xray.TestMultiScanId}, - {name: "InvalidGitInfoContext", gitInfoContext: &xray.GitInfoContextWithMissingFields, expected: xray.XscGitInfoBadResponse}, - } - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - sendGitInfoContext(t, test.gitInfoContext, test.expected) - }) - } -} - -func sendGitInfoContext(t *testing.T, gitInfoContext *xrayServices.XscGitInfoContext, expected string) { - result, err := testsScanService.SendScanGitInfoContext(gitInfoContext) - if err != nil { - assert.ErrorContains(t, err, expected) - return - } - assert.Equal(t, expected, result) -} - -func initXrayScanTest(t *testing.T) (xrayServerPort int, xrayDetails auth.ServiceDetails, client *jfroghttpclient.JfrogHttpClient) { - var err error - initXrayTest(t) - xrayServerPort = xray.StartXrayMockServer(t) - xrayDetails = GetXrayDetails() - client, err = jfroghttpclient.JfrogClientBuilder(). - SetClientCertPath(xrayDetails.GetClientCertPath()). - SetClientCertKeyPath(xrayDetails.GetClientCertKeyPath()). - AppendPreRequestInterceptor(xrayDetails.RunPreRequestFunctions). - Build() - assert.NoError(t, err) - return -} diff --git a/xray/manager.go b/xray/manager.go index 9667e681a..845688c41 100644 --- a/xray/manager.go +++ b/xray/manager.go @@ -4,7 +4,8 @@ import ( "github.com/jfrog/jfrog-client-go/config" "github.com/jfrog/jfrog-client-go/http/jfroghttpclient" "github.com/jfrog/jfrog-client-go/xray/services" - "github.com/jfrog/jfrog-client-go/xray/services/utils" + xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils" + "github.com/jfrog/jfrog-client-go/xray/services/xsc" ) // XrayServicesManager defines the http client and general configuration @@ -50,7 +51,7 @@ func (sm *XrayServicesManager) GetVersion() (string, error) { } // CreateWatch will create a new Xray watch -func (sm *XrayServicesManager) CreateWatch(params utils.WatchParams) error { +func (sm *XrayServicesManager) CreateWatch(params xrayUtils.WatchParams) error { watchService := services.NewWatchService(sm.client) watchService.XrayDetails = sm.config.GetServiceDetails() return watchService.Create(params) @@ -58,7 +59,7 @@ func (sm *XrayServicesManager) CreateWatch(params utils.WatchParams) error { // GetWatch retrieves the details about an Xray watch by name // It will error if no watch can be found by that name. -func (sm *XrayServicesManager) GetWatch(watchName string) (*utils.WatchParams, error) { +func (sm *XrayServicesManager) GetWatch(watchName string) (*xrayUtils.WatchParams, error) { watchService := services.NewWatchService(sm.client) watchService.XrayDetails = sm.config.GetServiceDetails() return watchService.Get(watchName) @@ -66,7 +67,7 @@ func (sm *XrayServicesManager) GetWatch(watchName string) (*utils.WatchParams, e // UpdateWatch will update an existing Xray watch by name // It will error if no watch can be found by that name. -func (sm *XrayServicesManager) UpdateWatch(params utils.WatchParams) error { +func (sm *XrayServicesManager) UpdateWatch(params xrayUtils.WatchParams) error { watchService := services.NewWatchService(sm.client) watchService.XrayDetails = sm.config.GetServiceDetails() return watchService.Update(params) @@ -81,7 +82,7 @@ func (sm *XrayServicesManager) DeleteWatch(watchName string) error { } // CreatePolicy will create a new Xray policy -func (sm *XrayServicesManager) CreatePolicy(params utils.PolicyParams) error { +func (sm *XrayServicesManager) CreatePolicy(params xrayUtils.PolicyParams) error { policyService := services.NewPolicyService(sm.client) policyService.XrayDetails = sm.config.GetServiceDetails() return policyService.Create(params) @@ -89,7 +90,7 @@ func (sm *XrayServicesManager) CreatePolicy(params utils.PolicyParams) error { // GetPolicy retrieves the details about an Xray policy by name // It will error if no policy can be found by that name. -func (sm *XrayServicesManager) GetPolicy(policyName string) (*utils.PolicyParams, error) { +func (sm *XrayServicesManager) GetPolicy(policyName string) (*xrayUtils.PolicyParams, error) { policyService := services.NewPolicyService(sm.client) policyService.XrayDetails = sm.config.GetServiceDetails() return policyService.Get(policyName) @@ -97,7 +98,7 @@ func (sm *XrayServicesManager) GetPolicy(policyName string) (*utils.PolicyParams // UpdatePolicy will update an existing Xray policy by name // It will error if no policy can be found by that name. -func (sm *XrayServicesManager) UpdatePolicy(params utils.PolicyParams) error { +func (sm *XrayServicesManager) UpdatePolicy(params xrayUtils.PolicyParams) error { policyService := services.NewPolicyService(sm.client) policyService.XrayDetails = sm.config.GetServiceDetails() return policyService.Update(params) @@ -113,7 +114,7 @@ func (sm *XrayServicesManager) DeletePolicy(policyName string) error { // CreatePolicy will create a new Xray ignore rule // The function returns the ignore rule id if succeeded or empty string and error message if fails -func (sm *XrayServicesManager) CreateIgnoreRule(params utils.IgnoreRuleParams) (string, error) { +func (sm *XrayServicesManager) CreateIgnoreRule(params xrayUtils.IgnoreRuleParams) (string, error) { ignoreRuleService := services.NewIgnoreRuleService(sm.client) ignoreRuleService.XrayDetails = sm.config.GetServiceDetails() return ignoreRuleService.Create(params) @@ -121,7 +122,7 @@ func (sm *XrayServicesManager) CreateIgnoreRule(params utils.IgnoreRuleParams) ( // CreatePolicy will create a new Xray ignore rule // The function returns the ignore rule id if succeeded or empty string and error message if fails -func (sm *XrayServicesManager) GetIgnoreRule(ignoreRuleId string) (*utils.IgnoreRuleParams, error) { +func (sm *XrayServicesManager) GetIgnoreRule(ignoreRuleId string) (*xrayUtils.IgnoreRuleParams, error) { ignoreRuleService := services.NewIgnoreRuleService(sm.client) ignoreRuleService.XrayDetails = sm.config.GetServiceDetails() return ignoreRuleService.Get(ignoreRuleId) @@ -158,10 +159,10 @@ func (sm *XrayServicesManager) ScanGraph(params services.XrayGraphScanParams) (s // GetScanGraphResults returns an Xray scan output of the requested graph scan. // The scanId input should be received from ScanGraph request. -func (sm *XrayServicesManager) GetScanGraphResults(scanID string, includeVulnerabilities, includeLicenses, xscEnabled bool) (*services.ScanResponse, error) { +func (sm *XrayServicesManager) GetScanGraphResults(scanID, xrayVersion string, includeVulnerabilities, includeLicenses, xscEnabled bool) (*services.ScanResponse, error) { scanService := services.NewScanService(sm.client) scanService.XrayDetails = sm.config.GetServiceDetails() - return scanService.GetScanGraphResults(scanID, includeVulnerabilities, includeLicenses, xscEnabled) + return scanService.GetScanGraphResults(scanID, xrayVersion, includeVulnerabilities, includeLicenses, xscEnabled) } func (sm *XrayServicesManager) ImportGraph(params services.XrayGraphImportParams) (scanId string, err error) { @@ -242,3 +243,10 @@ func (sm *XrayServicesManager) IsEntitled(featureId string) (bool, error) { entitlementsService.XrayDetails = sm.config.GetServiceDetails() return entitlementsService.IsEntitled(featureId) } + +// Xsc returns the Xsc service inside Xray +func (sm *XrayServicesManager) Xsc() *xsc.XscInnerService { + xscService := xsc.NewXscService(sm.client) + xscService.XrayDetails = sm.config.GetServiceDetails() + return xscService +} diff --git a/xray/services/scan.go b/xray/services/scan.go index 53fcb0644..0b33e2518 100644 --- a/xray/services/scan.go +++ b/xray/services/scan.go @@ -8,6 +8,7 @@ import ( "github.com/jfrog/jfrog-client-go/utils/log" xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils" + "github.com/jfrog/jfrog-client-go/xsc/services/utils" "github.com/jfrog/jfrog-client-go/auth" "github.com/jfrog/jfrog-client-go/http/jfroghttpclient" @@ -39,20 +40,13 @@ const ( xrayScanStatusFailed = "failed" - // Xsc consts - postXscGitInfoContextAPI = "api/v1/gitinfo" - - XscGraphAPI = "api/v1/sca/scan/graph" + XscGraphAPI = "sca/scan/graph" multiScanIdParam = "multi_scan_id=" scanTechQueryParam = "tech=" - XscVersionAPI = "api/v1/system/version" - - XraySuffix = "/xray/" - - XscSuffix = "/xsc/" + XscVersionAPI = "system/version" ) type ScanType string @@ -119,8 +113,8 @@ func (ss *ScanService) ScanGraph(scanParams XrayGraphScanParams) (string, error) url := ss.XrayDetails.GetUrl() + scanGraphAPI // When XSC is enabled, modify the URL. - if scanParams.XscVersion != "" { - url = ss.xrayToXscUrl() + XscGraphAPI + if scanParams.XrayVersion != "" && scanParams.XscVersion != "" { + url = utils.XrayUrlToXscUrl(ss.XrayDetails.GetUrl(), scanParams.XrayVersion) + XscGraphAPI } url += createScanGraphQueryParams(scanParams) resp, body, err := ss.client.SendPost(url, requestBody, &httpClientsDetails) @@ -142,7 +136,7 @@ func (ss *ScanService) ScanGraph(scanParams XrayGraphScanParams) (string, error) return scanResponse.ScanId, err } -func (ss *ScanService) GetScanGraphResults(scanId string, includeVulnerabilities, includeLicenses, xscEnabled bool) (*ScanResponse, error) { +func (ss *ScanService) GetScanGraphResults(scanId, xrayVersion string, includeVulnerabilities, includeLicenses, xscEnabled bool) (*ScanResponse, error) { httpClientsDetails := ss.XrayDetails.CreateHttpClientDetails() httpClientsDetails.SetContentTypeApplicationJson() @@ -150,7 +144,7 @@ func (ss *ScanService) GetScanGraphResults(scanId string, includeVulnerabilities endPoint := ss.XrayDetails.GetUrl() + scanGraphAPI // Modify endpoint if XSC is enabled if xscEnabled { - endPoint = ss.xrayToXscUrl() + XscGraphAPI + endPoint = utils.XrayUrlToXscUrl(ss.XrayDetails.GetUrl(), xrayVersion) + XscGraphAPI } endPoint += "/" + scanId @@ -186,63 +180,6 @@ func (ss *ScanService) GetScanGraphResults(scanId string, includeVulnerabilities return &scanResponse, err } -func (ss *ScanService) xrayToXscUrl() string { - return strings.Replace(ss.XrayDetails.GetUrl(), XraySuffix, XscSuffix, 1) -} - -func (ss *ScanService) SendScanGitInfoContext(details *XscGitInfoContext) (multiScanId string, err error) { - httpClientsDetails := ss.XrayDetails.CreateHttpClientDetails() - httpClientsDetails.SetContentTypeApplicationJson() - requestBody, err := json.Marshal(details) - if err != nil { - return "", errorutils.CheckError(err) - } - url := ss.xrayToXscUrl() + postXscGitInfoContextAPI - resp, body, err := ss.client.SendPost(url, requestBody, &httpClientsDetails) - if err != nil { - return - } - if err = errorutils.CheckResponseStatusWithBody(resp, body, http.StatusCreated); err != nil { - return - } - xscResponse := XscPostContextResponse{} - if err = json.Unmarshal(body, &xscResponse); err != nil { - return "", errorutils.CheckError(err) - } - return xscResponse.MultiScanId, err -} - -// IsXscEnabled will try to get XSC version. If route is not available, user is not entitled for XSC. -func (ss *ScanService) IsXscEnabled() (xsxVersion string, err error) { - httpClientsDetails := ss.XrayDetails.CreateHttpClientDetails() - url := ss.XrayDetails.GetUrl() - // If Xray suffix not found, Xsc is not supported. - if !strings.HasSuffix(url, XraySuffix) { - return - } - url = ss.xrayToXscUrl() - resp, body, _, err := ss.client.SendGet(url+XscVersionAPI, false, &httpClientsDetails) - if err != nil { - err = errorutils.CheckErrorf("failed to get JFrog XSC version, response: " + err.Error()) - return - } - if err = errorutils.CheckResponseStatusWithBody(resp, body, http.StatusOK, http.StatusNotFound); err != nil { - return - } - // When XSC is disabled, StatusNotFound is expected. Don't return error as this is optional. - if resp.StatusCode == http.StatusNotFound { - return - } - versionResponse := XscVersionResponse{} - if err = json.Unmarshal(body, &versionResponse); err != nil { - err = errorutils.CheckErrorf("failed to parse JFrog XSC server response: " + err.Error()) - return - } - xsxVersion = versionResponse.Version - log.Debug("XSC version:", xsxVersion) - return -} - type XrayGraphScanParams struct { // A path in Artifactory that this Artifact is intended to be deployed to. // This will provide a way to extract the watches that should be applied on this graph @@ -258,6 +195,7 @@ type XrayGraphScanParams struct { IncludeLicenses bool XscGitInfoContext *XscGitInfoContext XscVersion string + XrayVersion string MultiScanId string } diff --git a/xray/services/xsc/xsc.go b/xray/services/xsc/xsc.go new file mode 100644 index 000000000..37977f610 --- /dev/null +++ b/xray/services/xsc/xsc.go @@ -0,0 +1,54 @@ +package xsc + +import ( + "github.com/jfrog/jfrog-client-go/auth" + "github.com/jfrog/jfrog-client-go/http/jfroghttpclient" + "github.com/jfrog/jfrog-client-go/xsc/services" +) + +// XscService is the Xray Source Control service in the Xray service, available from v3.108.0. +// This service replaces the Xray Source Control service, which was available as a standalone service. +type XscInnerService struct { + client *jfroghttpclient.JfrogHttpClient + XrayDetails auth.ServiceDetails +} + +func NewXscService(client *jfroghttpclient.JfrogHttpClient) *XscInnerService { + return &XscInnerService{client: client} +} + +func (xs *XscInnerService) GetVersion() (string, error) { + versionService := services.NewVersionService(xs.client) + versionService.XrayDetails = xs.XrayDetails + return versionService.GetVersion() +} + +func (xs *XscInnerService) AddAnalyticsGeneralEvent(event services.XscAnalyticsGeneralEvent) (string, error) { + eventService := services.NewAnalyticsEventService(xs.client) + eventService.XrayDetails = xs.XrayDetails + return eventService.AddGeneralEvent(event) +} + +func (xs *XscInnerService) SendXscLogErrorRequest(errorLog *services.ExternalErrorLog) error { + logErrorService := services.NewLogErrorEventService(xs.client) + logErrorService.XrayDetails = xs.XrayDetails + return logErrorService.SendLogErrorEvent(errorLog) +} + +func (xs *XscInnerService) UpdateAnalyticsGeneralEvent(event services.XscAnalyticsGeneralEventFinalize) error { + eventService := services.NewAnalyticsEventService(xs.client) + eventService.XrayDetails = xs.XrayDetails + return eventService.UpdateGeneralEvent(event) +} + +func (xs *XscInnerService) GetAnalyticsGeneralEvent(msi string) (*services.XscAnalyticsGeneralEvent, error) { + eventService := services.NewAnalyticsEventService(xs.client) + eventService.XrayDetails = xs.XrayDetails + return eventService.GetGeneralEvent(msi) +} + +func (xs *XscInnerService) GetConfigProfile(profileName string) (*services.ConfigProfile, error) { + configProfileService := services.NewConfigurationProfileService(xs.client) + configProfileService.XrayDetails = xs.XrayDetails + return configProfileService.GetConfigurationProfile(profileName) +} diff --git a/xsc/manager.go b/xsc/manager.go index ff07b47b5..e86b53357 100644 --- a/xsc/manager.go +++ b/xsc/manager.go @@ -7,6 +7,7 @@ import ( ) // XscServicesManager defines the http client and general configuration +// Deprecated from Xray version 3.108.0, XSC is transitioning to Xray as inner service. type XscServicesManager struct { client *jfroghttpclient.JfrogHttpClient config config.Config diff --git a/xsc/service.go b/xsc/service.go new file mode 100644 index 000000000..6094b5b0d --- /dev/null +++ b/xsc/service.go @@ -0,0 +1,20 @@ +package xsc + +import "github.com/jfrog/jfrog-client-go/xsc/services" + +// XscService defines the API to interact with XSC +type XscService interface { + // GetVersion will return the Xsc version + GetVersion() (string, error) + // AddAnalyticsGeneralEvent will send an analytics metrics general event to Xsc and return MSI (multi scan id) generated by Xsc. + AddAnalyticsGeneralEvent(event services.XscAnalyticsGeneralEvent) (string, error) + // SendXscLogErrorRequest will send an error log to Xsc + SendXscLogErrorRequest(errorLog *services.ExternalErrorLog) error + // UpdateAnalyticsGeneralEvent upon completion of the scan and we have all the results to report on, + // we send a finalized analytics metrics event with information matching an existing event's msi. + UpdateAnalyticsGeneralEvent(event services.XscAnalyticsGeneralEventFinalize) error + // GetAnalyticsGeneralEvent returns general event that match the msi provided. + GetAnalyticsGeneralEvent(msi string) (*services.XscAnalyticsGeneralEvent, error) + // GetConfigProfile returns the configuration profile that match the profile name provided. + GetConfigProfile(profileName string) (*services.ConfigProfile, error) +} diff --git a/xsc/services/analytics.go b/xsc/services/analytics.go index 4162a30f5..8603f7e9f 100644 --- a/xsc/services/analytics.go +++ b/xsc/services/analytics.go @@ -3,41 +3,76 @@ package services import ( "encoding/json" "fmt" + "net/http" + "github.com/jfrog/jfrog-client-go/auth" "github.com/jfrog/jfrog-client-go/http/jfroghttpclient" "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/xray/services" - "net/http" + xscutils "github.com/jfrog/jfrog-client-go/xsc/services/utils" ) const ( AnalyticsMetricsMinXscVersion = "1.7.1" - xscEventApi = "api/v1/event" + xscEventApi = "event" + xscDeprecatedEventApiSuffix = "api/v1/" + xscEventApi ) type AnalyticsEventService struct { - client *jfroghttpclient.JfrogHttpClient - XscDetails auth.ServiceDetails + client *jfroghttpclient.JfrogHttpClient + XscDetails auth.ServiceDetails + XrayDetails auth.ServiceDetails } func NewAnalyticsEventService(client *jfroghttpclient.JfrogHttpClient) *AnalyticsEventService { return &AnalyticsEventService{client: client} } -// GetXscDetails returns the Xsc details -func (vs *AnalyticsEventService) GetXscDetails() auth.ServiceDetails { - return vs.XscDetails +func (vs *AnalyticsEventService) sendPostRequest(requestContent []byte) (resp *http.Response, body []byte, err error) { + if vs.XrayDetails != nil { + httpClientDetails := vs.XrayDetails.CreateHttpClientDetails() + resp, body, err = vs.client.SendPost(utils.AddTrailingSlashIfNeeded(vs.XrayDetails.GetUrl())+xscutils.XscInXraySuffix+xscEventApi, requestContent, &httpClientDetails) + return + } + // Backward compatibility + httpClientDetails := vs.XscDetails.CreateHttpClientDetails() + resp, body, err = vs.client.SendPost(utils.AddTrailingSlashIfNeeded(vs.XscDetails.GetUrl())+xscDeprecatedEventApiSuffix, requestContent, &httpClientDetails) + return +} + +func (vs *AnalyticsEventService) sendPutRequest(requestContent []byte) (resp *http.Response, body []byte, err error) { + if vs.XrayDetails != nil { + httpClientDetails := vs.XrayDetails.CreateHttpClientDetails() + resp, body, err = vs.client.SendPut(utils.AddTrailingSlashIfNeeded(vs.XrayDetails.GetUrl())+xscutils.XscInXraySuffix+xscEventApi, requestContent, &httpClientDetails) + return + } + // Backward compatibility + httpClientDetails := vs.XscDetails.CreateHttpClientDetails() + resp, body, err = vs.client.SendPut(utils.AddTrailingSlashIfNeeded(vs.XscDetails.GetUrl())+xscDeprecatedEventApiSuffix, requestContent, &httpClientDetails) + return +} + +func (vs *AnalyticsEventService) sendGetRequest(msi string) (resp *http.Response, body []byte, err error) { + if vs.XrayDetails != nil { + httpClientDetails := vs.XrayDetails.CreateHttpClientDetails() + resp, body, _, err = vs.client.SendGet(fmt.Sprintf("%s%s%s/%s", vs.XrayDetails.GetUrl(), xscutils.XscInXraySuffix, xscEventApi, msi), true, &httpClientDetails) + return + } + // Backward compatibility + httpClientDetails := vs.XscDetails.CreateHttpClientDetails() + resp, body, _, err = vs.client.SendGet(fmt.Sprintf("%s%s/%s", vs.XscDetails.GetUrl(), xscDeprecatedEventApiSuffix, msi), true, &httpClientDetails) + return + } // AddGeneralEvent add general event in Xsc and returns msi generated by Xsc. func (vs *AnalyticsEventService) AddGeneralEvent(event XscAnalyticsGeneralEvent) (string, error) { - httpDetails := vs.XscDetails.CreateHttpClientDetails() requestContent, err := json.Marshal(event) if err != nil { return "", errorutils.CheckError(err) } - resp, body, err := vs.client.SendPost(vs.XscDetails.GetUrl()+xscEventApi, requestContent, &httpDetails) + resp, body, err := vs.sendPostRequest(requestContent) if err != nil { return "", err } @@ -51,12 +86,11 @@ func (vs *AnalyticsEventService) AddGeneralEvent(event XscAnalyticsGeneralEvent) // UpdateGeneralEvent update finalized analytics metrics info of an existing event. func (vs *AnalyticsEventService) UpdateGeneralEvent(event XscAnalyticsGeneralEventFinalize) error { - httpDetails := vs.XscDetails.CreateHttpClientDetails() requestContent, err := json.Marshal(event) if err != nil { return errorutils.CheckError(err) } - resp, body, err := vs.client.SendPut(vs.XscDetails.GetUrl()+xscEventApi, requestContent, &httpDetails) + resp, body, err := vs.sendPutRequest(requestContent) if err != nil { return err } @@ -68,8 +102,7 @@ func (vs *AnalyticsEventService) UpdateGeneralEvent(event XscAnalyticsGeneralEve // GetGeneralEvent returns event's data matching the provided multi scan id. func (vs *AnalyticsEventService) GetGeneralEvent(msi string) (*XscAnalyticsGeneralEvent, error) { - httpDetails := vs.XscDetails.CreateHttpClientDetails() - resp, body, _, err := vs.client.SendGet(fmt.Sprintf("%s%s/%s", vs.XscDetails.GetUrl(), xscEventApi, msi), true, &httpDetails) + resp, body, err := vs.sendGetRequest(msi) if err != nil { return nil, err } diff --git a/xsc/services/logerrorevent.go b/xsc/services/logerrorevent.go index 54bd7946e..9afe4dad8 100644 --- a/xsc/services/logerrorevent.go +++ b/xsc/services/logerrorevent.go @@ -7,17 +7,20 @@ import ( "github.com/jfrog/jfrog-client-go/http/jfroghttpclient" "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/errorutils" + xscutils "github.com/jfrog/jfrog-client-go/xsc/services/utils" "net/http" ) const ( - postLogErrorAPI = "api/v1/event/logMessage" - LogErrorMinXscVersion = AnalyticsMetricsMinXscVersion + xscLogErrorApiSuffix = "event/logMessage" + xscDeprecatedLogErrorApiSuffix = "api/v1/" + xscLogErrorApiSuffix + LogErrorMinXscVersion = AnalyticsMetricsMinXscVersion ) type LogErrorEventService struct { - client *jfroghttpclient.JfrogHttpClient - XscDetails auth.ServiceDetails + client *jfroghttpclient.JfrogHttpClient + XscDetails auth.ServiceDetails + XrayDetails auth.ServiceDetails } type ExternalErrorLog struct { @@ -30,14 +33,26 @@ func NewLogErrorEventService(client *jfroghttpclient.JfrogHttpClient) *LogErrorE return &LogErrorEventService{client: client} } -func (les *LogErrorEventService) SendLogErrorEvent(errorLog *ExternalErrorLog) error { +func (les *LogErrorEventService) sendLogErrorRequest(requestContent []byte) (url string, resp *http.Response, body []byte, err error) { + if les.XrayDetails != nil { + httpClientDetails := les.XrayDetails.CreateHttpClientDetails() + url = utils.AddTrailingSlashIfNeeded(les.XrayDetails.GetUrl()) + xscutils.XscInXraySuffix + xscLogErrorApiSuffix + resp, body, err = les.client.SendPost(url, requestContent, &httpClientDetails) + return + } + // Backward compatibility httpClientDetails := les.XscDetails.CreateHttpClientDetails() + url = utils.AddTrailingSlashIfNeeded(les.XscDetails.GetUrl()) + xscDeprecatedLogErrorApiSuffix + resp, body, err = les.client.SendPost(url, requestContent, &httpClientDetails) + return +} + +func (les *LogErrorEventService) SendLogErrorEvent(errorLog *ExternalErrorLog) error { requestContent, err := json.Marshal(errorLog) if err != nil { return fmt.Errorf("failed to convert POST request body's struct into JSON: %q", err) } - url := utils.AddTrailingSlashIfNeeded(les.XscDetails.GetUrl()) + postLogErrorAPI - response, body, err := les.client.SendPost(url, requestContent, &httpClientDetails) + url, response, body, err := les.sendLogErrorRequest(requestContent) if err != nil { return fmt.Errorf("failed to send POST query to '%s': %s", url, err.Error()) } diff --git a/xsc/services/profile.go b/xsc/services/profile.go index 7b750f91b..2db33d7d7 100644 --- a/xsc/services/profile.go +++ b/xsc/services/profile.go @@ -3,21 +3,25 @@ package services import ( "encoding/json" "fmt" + "net/http" + "github.com/jfrog/jfrog-client-go/auth" "github.com/jfrog/jfrog-client-go/http/jfroghttpclient" "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/errorutils" - "net/http" + xscutils "github.com/jfrog/jfrog-client-go/xsc/services/utils" ) const ( - ConfigProfileMinXscVersion = "1.11.0" - xscConfigProfileApi = "api/v1/profile" + ConfigProfileMinXscVersion = "1.11.0" + xscConfigProfileApi = "profile" + xscDeprecatedConfigProfileApiSuffix = "api/v1/" + xscConfigProfileApi ) type ConfigurationProfileService struct { - client *jfroghttpclient.JfrogHttpClient - XscDetails auth.ServiceDetails + client *jfroghttpclient.JfrogHttpClient + XscDetails auth.ServiceDetails + XrayDetails auth.ServiceDetails } func NewConfigurationProfileService(client *jfroghttpclient.JfrogHttpClient) *ConfigurationProfileService { @@ -96,10 +100,22 @@ type ServicesScannerConfig struct { ExcludePatterns []string `json:"exclude_patterns,omitempty"` } -func (cp *ConfigurationProfileService) GetConfigurationProfile(profileName string) (*ConfigProfile, error) { +func (cp *ConfigurationProfileService) sendConfigProfileRequest(profileName string) (url string, resp *http.Response, body []byte, err error) { + if cp.XrayDetails != nil { + httpDetails := cp.XrayDetails.CreateHttpClientDetails() + url = fmt.Sprintf("%s%s%s/%s", utils.AddTrailingSlashIfNeeded(cp.XrayDetails.GetUrl()), xscutils.XscInXraySuffix, xscConfigProfileApi, profileName) + resp, body, _, err = cp.client.SendGet(url, true, &httpDetails) + return + } + // Backward compatibility httpDetails := cp.XscDetails.CreateHttpClientDetails() - url := fmt.Sprintf("%s%s/%s", utils.AddTrailingSlashIfNeeded(cp.XscDetails.GetUrl()), xscConfigProfileApi, profileName) - res, body, _, err := cp.client.SendGet(url, true, &httpDetails) + url = fmt.Sprintf("%s%s/%s", utils.AddTrailingSlashIfNeeded(cp.XscDetails.GetUrl()), xscDeprecatedConfigProfileApiSuffix, profileName) + resp, body, _, err = cp.client.SendGet(url, true, &httpDetails) + return +} + +func (cp *ConfigurationProfileService) GetConfigurationProfile(profileName string) (*ConfigProfile, error) { + url, res, body, err := cp.sendConfigProfileRequest(profileName) if err != nil { return nil, fmt.Errorf("failed to send GET query to '%s': %q", url, err) } diff --git a/xsc/services/utils/utils.go b/xsc/services/utils/utils.go new file mode 100644 index 000000000..24693e65b --- /dev/null +++ b/xsc/services/utils/utils.go @@ -0,0 +1,34 @@ +package utils + +import ( + "fmt" + "strings" + + "github.com/jfrog/jfrog-client-go/utils" + "github.com/jfrog/jfrog-client-go/utils/log" +) + +const ( + XraySuffix = "/xray/" + xscSuffix = "/xsc/" + apiV1Suffix = "api/v1" + XscInXraySuffix = apiV1Suffix + xscSuffix + MinXrayVersionXscTransitionToXray = "3.108.0" +) + +// From Xray version 3.108.0, XSC is transitioning to Xray as inner service. This function will return compatible URL. +func XrayUrlToXscUrl(xrayUrl, xrayVersion string) string { + if !IsXscXrayInnerService(xrayVersion) { + log.Debug(fmt.Sprintf("Xray version is lower than %s, XSC is not an inner service in Xray.", MinXrayVersionXscTransitionToXray)) + return strings.Replace(xrayUrl, XraySuffix, xscSuffix, 1) + apiV1Suffix + "/" + } + // Newer versions of Xray will have XSC as an inner service. + return xrayUrl + XscInXraySuffix +} + +func IsXscXrayInnerService(xrayVersion string) bool { + if err := utils.ValidateMinimumVersion(utils.Xray, xrayVersion, MinXrayVersionXscTransitionToXray); err != nil { + return false + } + return true +} diff --git a/xsc/services/utils/utils_test.go b/xsc/services/utils/utils_test.go new file mode 100644 index 000000000..718c75019 --- /dev/null +++ b/xsc/services/utils/utils_test.go @@ -0,0 +1,23 @@ +package utils + +import "testing" + +func TestXrayUrlToXscUrl(t *testing.T) { + tests := []struct { + testName string + xrayUrl string + xrayVersion string + expectedValue string + }{ + {"after transition", "http://platform.jfrog.io/xray/", "3.108.0", "http://platform.jfrog.io/xray/api/v1/xsc/"}, + {"before transition", "http://platform.jfrog.io/xray/", "3.107.0", "http://platform.jfrog.io/xsc/api/v1/"}, + } + for _, test := range tests { + t.Run(test.testName, func(t *testing.T) { + actualValue := XrayUrlToXscUrl(test.xrayUrl, test.xrayVersion) + if actualValue != test.expectedValue { + t.Error(test.testName, "Expecting:", test.expectedValue, "Got:", actualValue) + } + }) + } +} diff --git a/xsc/services/version.go b/xsc/services/version.go index 1f4a62f1f..d4786fe43 100644 --- a/xsc/services/version.go +++ b/xsc/services/version.go @@ -2,6 +2,7 @@ package services import ( "encoding/json" + "fmt" "net/http" "strings" @@ -9,12 +10,19 @@ import ( "github.com/jfrog/jfrog-client-go/http/jfroghttpclient" "github.com/jfrog/jfrog-client-go/utils" "github.com/jfrog/jfrog-client-go/utils/errorutils" + xscutils "github.com/jfrog/jfrog-client-go/xsc/services/utils" +) + +const ( + xscVersionApiSuffix = "system/version" + xscDeprecatedVersionApiSuffix = "api/v1/" + xscVersionApiSuffix ) // VersionService returns the https client and Xsc details type VersionService struct { - client *jfroghttpclient.JfrogHttpClient - XscDetails auth.ServiceDetails + client *jfroghttpclient.JfrogHttpClient + XscDetails auth.ServiceDetails + XrayDetails auth.ServiceDetails } // NewVersionService creates a new service to retrieve the version of Xsc @@ -22,19 +30,29 @@ func NewVersionService(client *jfroghttpclient.JfrogHttpClient) *VersionService return &VersionService{client: client} } -// GetXscDetails returns the Xsc details -func (vs *VersionService) GetXscDetails() auth.ServiceDetails { - return vs.XscDetails +func (vs *VersionService) sendVersionRequest() (resp *http.Response, body []byte, err error) { + if vs.XrayDetails != nil { + httpDetails := vs.XrayDetails.CreateHttpClientDetails() + resp, body, _, err = vs.client.SendGet(vs.XrayDetails.GetUrl()+xscutils.XscInXraySuffix+xscVersionApiSuffix, true, &httpDetails) + return + } + // Backward compatibility + httpDetails := vs.XscDetails.CreateHttpClientDetails() + resp, body, _, err = vs.client.SendGet(vs.XscDetails.GetUrl()+xscDeprecatedVersionApiSuffix, true, &httpDetails) + return } // GetVersion returns the version of Xsc func (vs *VersionService) GetVersion() (string, error) { - httpDetails := vs.XscDetails.CreateHttpClientDetails() - resp, body, _, err := vs.client.SendGet(vs.XscDetails.GetUrl()+"api/v1/system/version", true, &httpDetails) + resp, body, err := vs.sendVersionRequest() if err != nil { return "", err } if err = errorutils.CheckResponseStatus(resp, http.StatusOK); err != nil { + if resp.StatusCode == http.StatusNotFound { + // When XSC is disabled, StatusNotFound is expected. Don't GenerateResponseError in this case. + return "", fmt.Errorf("xsc is not available for this server") + } return "", errorutils.CheckError(errorutils.GenerateResponseError(resp.Status, utils.IndentJson(body))) } var version xscVersion From 443e60bc1d6bd8d09bb691bb04a9dc54f0f04d50 Mon Sep 17 00:00:00 2001 From: Or Zinger <94623525+orz25@users.noreply.github.com> Date: Tue, 26 Nov 2024 14:03:32 +0200 Subject: [PATCH 3/4] Change xsc in xray min version to 3.107.13 (#1048) --- xray/services/xsc/xsc.go | 2 +- xsc/manager.go | 2 +- xsc/services/utils/utils.go | 4 ++-- xsc/services/utils/utils_test.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/xray/services/xsc/xsc.go b/xray/services/xsc/xsc.go index 37977f610..cc5119a99 100644 --- a/xray/services/xsc/xsc.go +++ b/xray/services/xsc/xsc.go @@ -6,7 +6,7 @@ import ( "github.com/jfrog/jfrog-client-go/xsc/services" ) -// XscService is the Xray Source Control service in the Xray service, available from v3.108.0. +// XscService is the Xray Source Control service in the Xray service, available from v3.107.13. // This service replaces the Xray Source Control service, which was available as a standalone service. type XscInnerService struct { client *jfroghttpclient.JfrogHttpClient diff --git a/xsc/manager.go b/xsc/manager.go index e86b53357..04423674b 100644 --- a/xsc/manager.go +++ b/xsc/manager.go @@ -7,7 +7,7 @@ import ( ) // XscServicesManager defines the http client and general configuration -// Deprecated from Xray version 3.108.0, XSC is transitioning to Xray as inner service. +// Deprecated from Xray version 3.107.13, XSC is transitioning to Xray as inner service. type XscServicesManager struct { client *jfroghttpclient.JfrogHttpClient config config.Config diff --git a/xsc/services/utils/utils.go b/xsc/services/utils/utils.go index 24693e65b..af62188b8 100644 --- a/xsc/services/utils/utils.go +++ b/xsc/services/utils/utils.go @@ -13,10 +13,10 @@ const ( xscSuffix = "/xsc/" apiV1Suffix = "api/v1" XscInXraySuffix = apiV1Suffix + xscSuffix - MinXrayVersionXscTransitionToXray = "3.108.0" + MinXrayVersionXscTransitionToXray = "3.107.13" ) -// From Xray version 3.108.0, XSC is transitioning to Xray as inner service. This function will return compatible URL. +// From Xray version 3.107.13, XSC is transitioning to Xray as inner service. This function will return compatible URL. func XrayUrlToXscUrl(xrayUrl, xrayVersion string) string { if !IsXscXrayInnerService(xrayVersion) { log.Debug(fmt.Sprintf("Xray version is lower than %s, XSC is not an inner service in Xray.", MinXrayVersionXscTransitionToXray)) diff --git a/xsc/services/utils/utils_test.go b/xsc/services/utils/utils_test.go index 718c75019..57cdaf8bb 100644 --- a/xsc/services/utils/utils_test.go +++ b/xsc/services/utils/utils_test.go @@ -9,8 +9,8 @@ func TestXrayUrlToXscUrl(t *testing.T) { xrayVersion string expectedValue string }{ - {"after transition", "http://platform.jfrog.io/xray/", "3.108.0", "http://platform.jfrog.io/xray/api/v1/xsc/"}, - {"before transition", "http://platform.jfrog.io/xray/", "3.107.0", "http://platform.jfrog.io/xsc/api/v1/"}, + {"after transition", "http://platform.jfrog.io/xray/", "3.107.13", "http://platform.jfrog.io/xray/api/v1/xsc/"}, + {"before transition", "http://platform.jfrog.io/xray/", "3.106.0", "http://platform.jfrog.io/xsc/api/v1/"}, } for _, test := range tests { t.Run(test.testName, func(t *testing.T) { From 4aecb2068369e4a8a8a24e4797d2bb3aecfd2e18 Mon Sep 17 00:00:00 2001 From: Eyal Ben Moshe Date: Wed, 27 Nov 2024 05:55:36 +0200 Subject: [PATCH 4/4] Promote to v1.48.1 (#1049) --- utils/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/utils.go b/utils/utils.go index 068a35eb0..17bec088e 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -28,7 +28,7 @@ import ( const ( Development = "development" Agent = "jfrog-client-go" - Version = "1.48.0" + Version = "1.48.1" ) const xrayDevVersion = "3.x-dev"