diff --git a/about_test.go b/about_test.go index 0fa695f..27d4252 100644 --- a/about_test.go +++ b/about_test.go @@ -12,7 +12,7 @@ import ( ) func TestAboutService_Get(t *testing.T) { - _, client := setUpContainer(t) + client := setUpContainer(t, testContainerOptions{}) about, err := client.About.Get(context.TODO()) require.NoError(t, err) @@ -30,7 +30,11 @@ func TestAboutService_Get(t *testing.T) { require.Equal(t, "Alpine", about.Framework.Name) } -func setUpContainer(t *testing.T) (testcontainers.Container, *Client) { +type testContainerOptions struct { + APIPermissions []string +} + +func setUpContainer(t *testing.T, options testContainerOptions) *Client { ctx := context.Background() container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ @@ -69,22 +73,19 @@ func setUpContainer(t *testing.T) (testcontainers.Container, *Client) { client, err = NewClient(apiURL, WithBearerToken(bearerToken)) require.NoError(t, err) - // TODO: Pass desired permissions as parameter to setUpContainer - team, err := client.Team.Create(ctx, Team{ - Name: "test", - Permissions: []Permission{ - { - Name: "VIEW_PORTFOLIO", - }, - }, - }) + team, err := client.Team.Create(ctx, Team{Name: "test"}) require.NoError(t, err) + for _, permissionName := range options.APIPermissions { + _, err = client.Permission.AddPermissionToTeam(ctx, Permission{Name: permissionName}, team.UUID) + require.NoError(t, err) + } + apiKey, err := client.Team.GenerateAPIKey(ctx, team.UUID) require.NoError(t, err) client, err = NewClient(apiURL, WithAPIKey(apiKey)) require.NoError(t, err) - return container, client + return client } diff --git a/bom.go b/bom.go index 37f50fb..e53a11e 100644 --- a/bom.go +++ b/bom.go @@ -6,6 +6,7 @@ import ( "github.com/google/uuid" "net/http" "net/url" + "strings" ) type BOMService struct { @@ -16,9 +17,11 @@ type BOMUploadRequest struct { ProjectUUID *uuid.UUID `json:"project,omitempty"` ProjectName string `json:"projectName,omitempty"` ProjectVersion string `json:"projectVersion,omitempty"` - ParentUUID *uuid.UUID `json:"parentUUID,omitempty"` // Since v4.8.0 - ParentName string `json:"parentName,omitempty"` // Since v4.8.0 - ParentVersion string `json:"parentVersion,omitempty"` // Since v4.8.0 + ProjectTags []Tag `json:"projectTags,omitempty"` // Since v4.12.0 + ParentUUID *uuid.UUID `json:"parentUUID,omitempty"` // Since v4.8.0 + ParentName string `json:"parentName,omitempty"` // Since v4.8.0 + ParentVersion string `json:"parentVersion,omitempty"` // Since v4.8.0 + IsLatest bool `json:"isLatestProjectVersion,omitempty"` // Since v4.12.0 AutoCreate bool `json:"autoCreate"` BOM string `json:"bom"` } @@ -111,6 +114,16 @@ func (bs BOMService) PostBom(ctx context.Context, uploadReq BOMUploadRequest) (t if uploadReq.ProjectVersion != "" { params["projectVersion"] = append(params["projectVersion"], uploadReq.ProjectVersion) } + if len(uploadReq.ProjectTags) > 0 { + tagNames := make([]string, len(uploadReq.ProjectTags)) + for i := range uploadReq.ProjectTags { + tagNames[i] = uploadReq.ProjectTags[i].Name + } + params["projectTags"] = append(params["projectTags"], strings.Join(tagNames, ",")) + } + if uploadReq.IsLatest { + params["isLatest"] = append(params["isLatest"], "true") + } if uploadReq.ParentUUID != nil { params["parentUUID"] = append(params["parentUUID"], uploadReq.ParentUUID.String()) } diff --git a/bom_test.go b/bom_test.go new file mode 100644 index 0000000..bf6e83d --- /dev/null +++ b/bom_test.go @@ -0,0 +1,78 @@ +package dtrack + +import ( + "context" + "encoding/base64" + "github.com/stretchr/testify/require" + "testing" +) + +func TestBOMService_Upload(t *testing.T) { + client := setUpContainer(t, testContainerOptions{ + APIPermissions: []string{ + PermissionBOMUpload, + PermissionProjectCreationUpload, + PermissionViewPortfolio, + }, + }) + + _, err := client.BOM.Upload(context.Background(), BOMUploadRequest{ + ProjectName: "acme-app", + ProjectVersion: "1.2.3", + ProjectTags: []Tag{ + {Name: "foo"}, + {Name: "bar"}, + }, + IsLatest: true, + AutoCreate: true, + BOM: base64.StdEncoding.EncodeToString([]byte(` +{ + "bomFormat": "CycloneDX", + "specVersion": "1.4", + "version": 1, + "components": [] +}`)), + }) + require.NoError(t, err) + + project, err := client.Project.Lookup(context.Background(), "acme-app", "1.2.3") + require.NoError(t, err) + require.Contains(t, project.Tags, Tag{Name: "foo"}) + require.Contains(t, project.Tags, Tag{Name: "bar"}) + require.True(t, project.IsLatest) +} + +func TestBOMService_PostBom(t *testing.T) { + client := setUpContainer(t, testContainerOptions{ + APIPermissions: []string{ + PermissionBOMUpload, + PermissionProjectCreationUpload, + PermissionViewPortfolio, + }, + }) + + _, err := client.BOM.PostBom(context.Background(), BOMUploadRequest{ + ProjectName: "acme-app", + ProjectVersion: "1.2.3", + ProjectTags: []Tag{ + {Name: "foo"}, + {Name: "bar"}, + }, + IsLatest: true, + AutoCreate: true, + BOM: ` +{ + "bomFormat": "CycloneDX", + "specVersion": "1.4", + "version": 1, + "components": [] +}`, + }) + require.NoError(t, err) + + project, err := client.Project.Lookup(context.Background(), "acme-app", "1.2.3") + require.NoError(t, err) + require.Contains(t, project.Tags, Tag{Name: "foo"}) + require.Contains(t, project.Tags, Tag{Name: "bar"}) + require.True(t, project.IsLatest) +} diff --git a/permission.go b/permission.go index 53b76e7..d25ce79 100644 --- a/permission.go +++ b/permission.go @@ -8,6 +8,23 @@ import ( "github.com/google/uuid" ) +const ( + PermissionAccessManagement = "ACCESS_MANAGEMENT" + PermissionBOMUpload = "BOM_UPLOAD" + PermissionPolicyManagement = "POLICY_MANAGEMENT" + PermissionPolicyViolationAnalysis = "POLICY_VIOLATION_ANALYSIS" + PermissionPortfolioManagement = "PORTFOLIO_MANAGEMENT" + PermissionProjectCreationUpload = "PROJECT_CREATION_UPLOAD" + PermissionSystemConfiguration = "SYSTEM_CONFIGURATION" + PermissionTagManagement = "TAG_MANAGEMENT" + PermissionViewBadges = "VIEW_BADGES" + PermissionViewPolicyViolation = "VIEW_POLICY_VIOLATION" + PermissionViewPortfolio = "VIEW_PORTFOLIO" + PermissionViewVulnerability = "VIEW_VULNERABILITY" + PermissionVulnerabilityAnalysis = "VULNERABILITY_ANALYSIS" + PermissionVulnerabilityManagement = "VULNERABILITY_MANAGEMENT" +) + type PermissionService struct { client *Client } diff --git a/project.go b/project.go index 44c5fee..8781f61 100644 --- a/project.go +++ b/project.go @@ -25,6 +25,7 @@ type Project struct { Properties []ProjectProperty `json:"properties,omitempty"` Tags []Tag `json:"tags,omitempty"` Active bool `json:"active"` + IsLatest bool `json:"isLatest"` // Since v4.12.0 Metrics ProjectMetrics `json:"metrics"` ParentRef *ParentRef `json:"parent,omitempty"` LastBOMImport int `json:"lastBomImport"`