Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New XSC analytics metrics capabilities. #928

Merged
merged 68 commits into from
Apr 3, 2024
Merged
Show file tree
Hide file tree
Changes from 67 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
1b94940
change branches
gailazar300 Dec 29, 2021
0df64cd
test
gailazar300 Dec 29, 2021
1edfa13
all branches
gailazar300 Dec 29, 2021
a664ea4
Promote version to 1.28.1 (#733)
omerzi Apr 5, 2023
0b22cb3
Added the Frogbot badge to the README (#740)
eyalbe4 Apr 13, 2023
93d1ee0
Merge remote-tracking branch 'upstream/dev' into masterupstream
sverdlov93 Apr 19, 2023
60012f0
Merge remote-tracking branch 'origin/dev'
omerzi May 2, 2023
72340a7
Merge branch 'dev'
eyalbe4 May 16, 2023
3c0e410
Merge remote-tracking branch 'origin/dev'
talarian1 May 17, 2023
7dd161b
Merge remote-tracking branch 'origin/dev'
omerzi May 21, 2023
88f4c5c
Merge remote-tracking branch 'origin/dev'
talarian1 May 23, 2023
21b99ad
Merge branch 'master' into dev
yahavi May 23, 2023
b71c280
Promoted version to 1.29.1
yahavi May 23, 2023
8f7755c
Merge branch 'dev'
eyalbe4 Jun 10, 2023
e6ba583
Merge branch 'dev'
eyalbe4 Jun 25, 2023
b624428
Merge branch 'dev'
RobiNino Jun 29, 2023
da0c018
Merge branch 'master' into dev
omerzi Jul 12, 2023
f750025
Promoted version to 1.31.1
omerzi Jul 12, 2023
e1d57bd
Merge remote-tracking branch 'origin/dev'
omerzi Jul 18, 2023
886ff5f
Merge branch 'dev'
eyalbe4 Jul 31, 2023
b1ae836
Promoted version to 1.31.3
eyalbe4 Jul 31, 2023
df38e23
Merge branch 'dev'
eyalbe4 Jul 31, 2023
46b7fb9
Merge branch 'dev'
eyalbe4 Aug 3, 2023
5f58723
Resolve conflicts
eyalbe4 Aug 3, 2023
080ef1a
Merge branch 'dev'
eyalbe4 Aug 23, 2023
7c244c5
Merge branch 'dev'
attiasas Aug 28, 2023
6d1c9e7
Merge branch 'master' into dev
EyalDelarea Sep 11, 2023
b3d917f
Merge remote-tracking branch 'origin/dev'
EyalDelarea Sep 11, 2023
3be412b
Merge remote-tracking branch 'upstream/dev'
sverdlov93 Sep 13, 2023
fa697b5
Merge branch 'dev'
RobiNino Sep 14, 2023
7b2943f
Merge remote-tracking branch 'origin/dev'
eranturgeman Oct 3, 2023
15552e7
Merge remote-tracking branch 'jfrog-prod/dev'
eranturgeman Oct 3, 2023
9684938
Merge remote-tracking branch 'origin/dev'
yahavi Oct 4, 2023
9dd7283
Merge branch 'dev'
EyalDelarea Oct 5, 2023
21998b7
Merge remote-tracking branch 'origin/dev'
omerzi Oct 17, 2023
dc27aae
Merge remote-tracking branch 'origin/dev'
attiasas Nov 8, 2023
0abdd92
Merge remote-tracking branch 'origin/dev'
yahavi Nov 9, 2023
696df1a
Merge remote-tracking branch 'upstream/dev'
yahavi Nov 30, 2023
c09e8dd
Merge branch 'dev'
eyalbe4 Dec 15, 2023
3edc13f
Promote to v1.35.2
eyalbe4 Dec 18, 2023
ddfd377
Merge branch 'master' into dev
eyalbe4 Dec 18, 2023
36e989c
Resolved conflict
eyalbe4 Dec 21, 2023
cc27960
Merge branch 'dev'
eyalbe4 Dec 25, 2023
7f02060
Promote version to 1.35.5
omerzi Dec 27, 2023
5dd6e86
Promote version to 1.35.6
omerzi Jan 7, 2024
4f0f4b7
Merge branch 'dev'
eyalbe4 Jan 22, 2024
e249dfe
Promote version to '1.36.1' (#892)
attiasas Jan 29, 2024
8b005ae
Merge changes to master (#907)
yahavi Feb 20, 2024
18d4ebf
Merge remote-tracking branch 'origin/dev'
yahavi Feb 20, 2024
14a4407
Merge remote-tracking branch 'origin/dev'
yahavi Feb 21, 2024
1aca291
Merge remote-tracking branch 'origin/dev'
RobiNino Mar 18, 2024
ed22625
XRAY-36905 - Add Analytics Metrics capabilities in CLI.
gailazar300 Mar 20, 2024
6d38f21
Merge remote-tracking branch 'upstream/master' into feature/XRAY-36905
gailazar300 Mar 20, 2024
1579176
Add POST general event.
gailazar300 Mar 24, 2024
a972545
Add new XscAddGeneralEventRequest struct.
gailazar300 Mar 26, 2024
336b75c
Before review fixes.
gailazar300 Mar 26, 2024
2e6841d
Add UpdateGeneralEvent and remove unnecessary xsc apis from xray serv…
gailazar300 Mar 27, 2024
0064d7a
Minor fixes.
gailazar300 Mar 31, 2024
0da6a25
Review fixes.
gailazar300 Mar 31, 2024
e2e7cd4
Merge remote-tracking branch 'upstream/dev' into feature/XRAY-36905
gailazar300 Mar 31, 2024
71b5429
Add data validation to the tests using GetGeneralEvent api.
gailazar300 Mar 31, 2024
bab8c9a
Add TestSetEnvWithResetCallback.
gailazar300 Apr 1, 2024
9b8da01
Add GetAnalyticsGeneralEvent.
gailazar300 Apr 1, 2024
8df71a3
Second review fixes.
gailazar300 Apr 2, 2024
015add4
Fix README.md.
gailazar300 Apr 2, 2024
f4a07a4
Minor change.
gailazar300 Apr 2, 2024
38badc2
Eyal's review fixes.
gailazar300 Apr 2, 2024
3003542
Minor fixes.
gailazar300 Apr 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ jobs:
strategy:
fail-fast: false
matrix:
suite: [ distribution, xray, mpu ]
suite: [ distribution, xray, xsc, mpu ]
os: [ ubuntu, windows, macos ]
runs-on: ${{ matrix.os }}-latest
steps:
Expand All @@ -114,7 +114,7 @@ jobs:
restore-keys: ${{ runner.os }}-go-

- name: ${{ matrix.suite }} tests
run: go test -v github.com/jfrog/jfrog-client-go/tests --timeout 0 --test.${{ matrix.suite }} --rt.url=${{ secrets.PLATFORM_URL }}/artifactory --ds.url=${{ secrets.PLATFORM_URL }}/distribution --xr.url=${{ secrets.PLATFORM_URL }}/xray --access.url=${{ secrets.PLATFORM_URL }}/access --rt.user=${{ secrets.PLATFORM_USER }} --rt.password=${{ secrets.PLATFORM_PASSWORD }} --access.token=${{ secrets.PLATFORM_ADMIN_TOKEN }} --ci.runId=${{ runner.os }}-${{ matrix.suite }}
run: go test -v github.com/jfrog/jfrog-client-go/tests --timeout 0 --test.${{ matrix.suite }} --rt.url=${{ secrets.PLATFORM_URL }}/artifactory --ds.url=${{ secrets.PLATFORM_URL }}/distribution --xr.url=${{ secrets.PLATFORM_URL }}/xray --xsc.url=${{ secrets.PLATFORM_URL }}/xsc --access.url=${{ secrets.PLATFORM_URL }}/access --rt.user=${{ secrets.PLATFORM_USER }} --rt.password=${{ secrets.PLATFORM_PASSWORD }} --access.token=${{ secrets.PLATFORM_ADMIN_TOKEN }} --ci.runId=${{ runner.os }}-${{ matrix.suite }}

JFrog-Client-Go-Pipelines-Tests:
needs: Pretest
Expand Down
98 changes: 88 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,17 @@
- [Delete Violations Report](#delete-violations-report)
- [Get Artifact Summary](#get-artifact-summary)
- [Get Entitlement info](#get-entitlement-info)
- [Using XSC Service](#using-xsc-service)
- [Check if xsc is enabled](#check-if-xsc-is-enabled)
- [Send git info details to xsc](#send-git-info-details-to-xsc)
- [XSC API](#xsc-apis)
gailazar300 marked this conversation as resolved.
Show resolved Hide resolved
- [Creating XSC Service Manager](#creating-xray-service-manager)
- [Creating XSC Details](#creating-xsc-details)
- [Creating XSC Service Config](#creating-xsc-service-config)
- [Creating New XSC Service Manager](#creating-new-xsc-service-manager)
- [Using XSC Services](#using-xsc-services)
- [Fetching XSC's Version](#fetching-xscs-version)
- [Report XSC analytics metrics](#report-xsc-analytics-metrics)
- [Add analytics general event](#add-analytics-general-event)
- [Update analytics general event](#update-analytics-general-event)
- [Get analytics general event](#get-analytics-general-event)
- [Pipelines APIs](#pipelines-apis)
- [Creating Pipelines Service Manager](#creating-pipelines-service-manager)
- [Creating Pipelines Details](#creating-pipelines-details)
Expand Down Expand Up @@ -265,6 +273,7 @@ content of this repository is deleted.
| `-test.artifactory` | Artifactory tests | Artifactory Pro |
| `-test.distribution` | Distribution tests | Artifactory with Distribution |
| `-test.xray` | Xray tests | Artifactory with Xray |
| `-test.xsc` | Xsc tests | Xray with Xsc |
| `-test.pipelines` | Pipelines tests | JFrog Pipelines |
| `-test.access` | Access tests | Artifactory Pro |
| `-test.repositories` | Repositories tests | Artifactory Pro |
Expand All @@ -277,6 +286,7 @@ content of this repository is deleted.
| `-rt.url` | [Default: http://localhost:8081/artifactory] Artifactory URL. |
| `-ds.url` | [Optional] JFrog Distribution URL. |
| `-xr.url` | [Optional] JFrog Xray URL. |
| `-xsc.url` | [Optional] JFrog Xsc URL. |
| `-pipe.url` | [Optional] JFrog Pipelines URL. |
| `-access.url` | [Optional] JFrog Access URL. |
| `-rt.user` | [Default: admin] Artifactory username. |
Expand Down Expand Up @@ -2233,20 +2243,88 @@ artifactSummary, err := xrayManager.ArtifactSummary(artifactSummaryRequest)
isEntitled, err := xrayManager.IsEntitled(featureId)
```

### Using XSC Service

#### Check if xsc is enabled
## XSC APIs

### Creating XSC Service Manager

#### Creating XSC Details

```go
xscDetails := auth.NewXscDetails()
xscDetails.SetUrl("http://localhost:8081/xsc")
xscDetails.SetSshKeyPath("path/to/.ssh/")
xscDetails.SetApiKey("apikey")
xscDetails.SetUser("user")
xscDetails.SetPassword("password")
xscDetails.SetAccessToken("accesstoken")
// if client certificates are required
xscDetails.SetClientCertPath("path/to/.cer")
xscDetails.SetClientCertKeyPath("path/to/.key")
```

#### Creating XSC Service Config

```go
serviceConfig, err := config.NewConfigBuilder().
SetServiceDetails(xscDetails).
SetCertificatesPath(certPath).
// Optionally overwrite the default HTTP retries, which is set to 3.
SetHttpRetries(8).
Build()
```

#### Creating New XSC Service Manager

```go
// Will try to get XSC version. If route is not available, user is not entitled for XSC.
xscVersion, err := scanService.IsXscEnabled()
xscManager, err := xsc.New(serviceConfig)
```

#### Send git info details to xsc
### Using XSC Services

#### Fetching XSC's Version

```go
version, err := xscManager.GetVersion()
```

#### Report XSC analytics metrics
##### Add analytics general event
Sent XSC a new event which contains analytics data, and get multi-scan id back from XSC.
```go
event := services.XscAnalyticsGeneralEvent{
XscAnalyticsBasicGeneralEvent: services.XscAnalyticsBasicGeneralEvent{
EventType: services.CliEventType,
Product: services.CliProduct,
ProductVersion: "2.53.1",
IsDefaultConfig: false,
JfrogUser: "gail",
OsPlatform: "mac",
OsArchitecture: "arm64",
AnalyzerManagerVersion: "1.1.1",
EventStatus: services.Started,
}}
msi, err := xscManager.AddAnalyticsGeneralEvent(event)
```
##### Update analytics general event
Sent XSC a finalized analytics metrics event with information matching an existing event's msi.
```go
finalizeEvent := services.XscAnalyticsGeneralEventFinalize{
MultiScanId: msi,
XscAnalyticsBasicGeneralEvent: services.XscAnalyticsBasicGeneralEvent{
EventStatus: services.Completed,
TotalFindings: 10,
TotalIgnoredFindings: 5,
TotalScanDuration: "15s",
},
}
err := xscManager.UpdateAnalyticsGeneralEvent(finalizeEvent)
```

##### Get analytics general event
Get a general event from XSC matching the provided msi.
```go
// Details are the git info details (gitRepoUrl, branchName, commitHash are required fields). Returns multi scan id.
multiScanId, err := scanService.SendScanGitInfoContext(details)
event, err := xscManager.GetAnalyticsGeneralEvent(msi)
```

## Pipelines APIs
Expand Down
12 changes: 12 additions & 0 deletions tests/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,23 @@ import (
"github.com/jfrog/jfrog-client-go/utils/log"
xrayAuth "github.com/jfrog/jfrog-client-go/xray/auth"
xrayServices "github.com/jfrog/jfrog-client-go/xray/services"
xscAuth "github.com/jfrog/jfrog-client-go/xsc/auth"
"github.com/stretchr/testify/assert"
)

var (
TestArtifactory *bool
TestDistribution *bool
TestXray *bool
TestXsc *bool
TestPipelines *bool
TestAccess *bool
TestRepositories *bool
TestMultipartUpload *bool
RtUrl *string
DistUrl *string
XrayUrl *string
XscUrl *string
gailazar300 marked this conversation as resolved.
Show resolved Hide resolved
PipelinesUrl *string
RtUser *string
RtPassword *string
Expand Down Expand Up @@ -145,13 +148,15 @@ func init() {
TestArtifactory = flag.Bool("test.artifactory", false, "Test Artifactory")
TestDistribution = flag.Bool("test.distribution", false, "Test distribution")
TestXray = flag.Bool("test.xray", false, "Test xray")
TestXsc = flag.Bool("test.xsc", false, "Test xsc")
gailazar300 marked this conversation as resolved.
Show resolved Hide resolved
TestPipelines = flag.Bool("test.pipelines", false, "Test pipelines")
TestAccess = flag.Bool("test.access", false, "Test access")
TestRepositories = flag.Bool("test.repositories", false, "Test repositories in Artifactory")
TestMultipartUpload = flag.Bool("test.mpu", false, "Test Artifactory multipart upload")
RtUrl = flag.String("rt.url", "http://localhost:8081/artifactory", "Artifactory url")
DistUrl = flag.String("ds.url", "", "Distribution url")
XrayUrl = flag.String("xr.url", "", "Xray url")
XscUrl = flag.String("xsc.url", "", "Xsc url")
PipelinesUrl = flag.String("pipe.url", "", "Pipelines url")
AccessUrl = flag.String("access.url", "http://localhost:8081/access", "Access url")
RtUser = flag.String("rt.user", "admin", "Artifactory username")
Expand Down Expand Up @@ -563,6 +568,13 @@ func GetXrayDetails() auth.ServiceDetails {
return xrayDetails
}

func GetXscDetails() auth.ServiceDetails {
xscDetails := xscAuth.NewXscDetails()
xscDetails.SetUrl(clientutils.AddTrailingSlashIfNeeded(*XscUrl))
setAuthenticationDetail(xscDetails)
return xscDetails
}

func GetPipelinesDetails() auth.ServiceDetails {
pDetails := pipelinesAuth.NewPipelinesDetails()
pDetails.SetUrl(clientutils.AddTrailingSlashIfNeeded(*PipelinesUrl))
Expand Down
36 changes: 36 additions & 0 deletions tests/xsc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package tests

import (
clientUtils "github.com/jfrog/jfrog-client-go/utils"
"testing"
)

func TestXscVersion(t *testing.T) {
initXscTest(t, "")
version, err := GetXscDetails().GetVersion()
if err != nil {
t.Error(err)
}
if version == "" {
t.Error("Expected a version, got empty string")
}
}

func initXscTest(t *testing.T, minVersion string) {
if !*TestXsc {
t.Skip("Skipping xsc test. To run xsc test add the '-test.xsc=true' option.")
}
validateXscVersion(t, minVersion)
}
func validateXscVersion(t *testing.T, minVersion string) {
// Validate active XSC server.
version, err := GetXscDetails().GetVersion()
if err != nil {
t.Skip(err)
}
// Validate minimum XSC version.
err = clientUtils.ValidateMinimumVersion(clientUtils.Xsc, version, minVersion)
if err != nil {
t.Skip(err)
}
}
79 changes: 79 additions & 0 deletions tests/xscanalyticsevent_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package tests

import (
"github.com/jfrog/jfrog-client-go/auth"
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
"github.com/jfrog/jfrog-client-go/xsc/services"
"github.com/stretchr/testify/assert"
"regexp"
"testing"
)

var testsEventService *services.AnalyticsEventService

func TestXscAddAndUpdateGeneralEvent(t *testing.T) {
xscDetails, client := initXscEventTest(t)
testsEventService = services.NewAnalyticsEventService(client)
testsEventService.XscDetails = xscDetails
gailazar300 marked this conversation as resolved.
Show resolved Hide resolved

event := services.XscAnalyticsGeneralEvent{XscAnalyticsBasicGeneralEvent: services.XscAnalyticsBasicGeneralEvent{
EventType: services.CliEventType,
EventStatus: services.Started,
Product: services.CliProduct,
ProductVersion: "2.53.1",
IsDefaultConfig: false,
JfrogUser: "gail",
OsPlatform: "mac",
OsArchitecture: "arm64",
MachineId: "id",
AnalyzerManagerVersion: "1.1.1",
}}
msi, err := testsEventService.AddGeneralEvent(event)
assert.NoError(t, err)
assert.True(t, isValidUUID(msi))

// Validate that the event sent and saved properly in XSC.
resp, err := testsEventService.GetGeneralEvent(msi)
assert.NoError(t, err)
assert.Equal(t, event, *resp)

finalizeEvent := services.XscAnalyticsGeneralEventFinalize{
MultiScanId: msi,
XscAnalyticsBasicGeneralEvent: services.XscAnalyticsBasicGeneralEvent{
EventStatus: services.Completed,
TotalFindings: 10,
TotalIgnoredFindings: 5,
TotalScanDuration: "15s",
},
}

err = testsEventService.UpdateGeneralEvent(finalizeEvent)
assert.NoError(t, err)
gailazar300 marked this conversation as resolved.
Show resolved Hide resolved

// Validate that the event's update sent and saved properly in XSC.
resp, err = testsEventService.GetGeneralEvent(msi)
assert.NoError(t, err)
event.EventStatus = services.Completed
event.TotalFindings = 10
event.TotalIgnoredFindings = 5
event.TotalScanDuration = "15s"
assert.Equal(t, event, *resp)
}

func isValidUUID(str string) bool {
uuidRegex := regexp.MustCompile(`^[0-9a-f]{8}-[0-9a-f]{4}-1[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$`)
return uuidRegex.MatchString(str)
}

func initXscEventTest(t *testing.T) (xscDetails auth.ServiceDetails, client *jfroghttpclient.JfrogHttpClient) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an issue I noticed here that if the url provided as a flag doesn't have a suffix of '/xsc', nothing adds it to the url. This may cause a 404 status code to return from the POST query. Do we trust the customer to provide the correct url with the /xsc suffix (since the flag that is suppose to be provided is -url.xsc and not -jfrog.url)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like any other server (rt/dist/xray) if the user want to run tests for this server he has to provide the relevant url with the relevant suffix.

var err error
initXscTest(t, services.AnalyticsMetricsMinXscVersion)
xscDetails = GetXscDetails()
client, err = jfroghttpclient.JfrogClientBuilder().
SetClientCertPath(xscDetails.GetClientCertPath()).
SetClientCertKeyPath(xscDetails.GetClientCertKeyPath()).
AppendPreRequestInterceptor(xscDetails.RunPreRequestFunctions).
Build()
assert.NoError(t, err)
return
}
28 changes: 28 additions & 0 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type MinVersionProduct string
const (
Artifactory MinVersionProduct = "JFrog Artifactory"
Xray MinVersionProduct = "JFrog Xray"
Xsc MinVersionProduct = "JFrog Xsc"
DataTransfer MinVersionProduct = "Data Transfer"
DockerApi MinVersionProduct = "Docker API"
Projects MinVersionProduct = "JFrog Projects"
Expand Down Expand Up @@ -601,3 +602,30 @@ func ExtractSha256FromResponseBody(body []byte) (string, error) {
func Pointer[K any](val K) *K {
return &val
}

func SetEnvWithResetCallback(key, value string) (func() error, error) {
oldValue, exist := os.LookupEnv(key)
errMsg := "failed %s %s as environment variable. Cause: %s"

if err := os.Setenv(key, value); err != nil {
log.Debug(fmt.Sprintf(errMsg, "setting", key, err.Error()))
gailazar300 marked this conversation as resolved.
Show resolved Hide resolved
return func() error { return nil }, err
}

if exist {
return func() error {
err := os.Setenv(key, oldValue)
if err != nil {
log.Debug(fmt.Sprintf(errMsg, "setting", key, err.Error()))
}
return err
}, nil
}
return func() error {
err := os.Unsetenv(key)
if err != nil {
log.Debug(fmt.Sprintf(errMsg, "unsetting", key, err.Error()))
}
return err
}, nil
}
Loading
Loading