From cea47c7db38f60d2e83343f933a0c1806eb2d583 Mon Sep 17 00:00:00 2001 From: "stonezdj(Daojun Zhang)" Date: Tue, 2 Apr 2024 18:11:27 +0800 Subject: [PATCH] Add accessory type for sbom (#20208) Signed-off-by: stonezdj Co-authored-by: stonezdj --- src/core/main.go | 1 + src/pkg/accessory/model/accessory.go | 3 + src/pkg/accessory/model/sbom/sbom.go | 46 ++++++++++++ src/pkg/accessory/model/sbom/sbom_test.go | 87 +++++++++++++++++++++++ src/server/middleware/subject/subject.go | 5 ++ 5 files changed, 142 insertions(+) create mode 100644 src/pkg/accessory/model/sbom/sbom.go create mode 100644 src/pkg/accessory/model/sbom/sbom_test.go diff --git a/src/core/main.go b/src/core/main.go index b660ea012..50e6a4566 100644 --- a/src/core/main.go +++ b/src/core/main.go @@ -60,6 +60,7 @@ import ( _ "github.com/goharbor/harbor/src/pkg/accessory/model/cosign" _ "github.com/goharbor/harbor/src/pkg/accessory/model/notation" _ "github.com/goharbor/harbor/src/pkg/accessory/model/nydus" + _ "github.com/goharbor/harbor/src/pkg/accessory/model/sbom" _ "github.com/goharbor/harbor/src/pkg/accessory/model/subject" "github.com/goharbor/harbor/src/pkg/audit" dbCfg "github.com/goharbor/harbor/src/pkg/config/db" diff --git a/src/pkg/accessory/model/accessory.go b/src/pkg/accessory/model/accessory.go index 4d6052532..5bd276c8e 100644 --- a/src/pkg/accessory/model/accessory.go +++ b/src/pkg/accessory/model/accessory.go @@ -76,6 +76,9 @@ const ( // TypeSubject ... TypeSubject = "subject.accessory" + + // TypeHarborSBOM identifies harbor.sbom + TypeHarborSBOM = "harbor.sbom" ) // AccessoryData ... diff --git a/src/pkg/accessory/model/sbom/sbom.go b/src/pkg/accessory/model/sbom/sbom.go new file mode 100644 index 000000000..3e5a5642a --- /dev/null +++ b/src/pkg/accessory/model/sbom/sbom.go @@ -0,0 +1,46 @@ +// Copyright Project Harbor Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sbom + +import ( + "github.com/goharbor/harbor/src/pkg/accessory/model" + "github.com/goharbor/harbor/src/pkg/accessory/model/base" +) + +// HarborSBOM is the sbom accessory for harbor +type HarborSBOM struct { + base.Default +} + +// Kind gives the reference type of accessory. +func (c *HarborSBOM) Kind() string { + return model.RefHard +} + +// IsHard ... +func (c *HarborSBOM) IsHard() bool { + return true +} + +// New returns sbom accessory +func New(data model.AccessoryData) model.Accessory { + return &HarborSBOM{base.Default{ + Data: data, + }} +} + +func init() { + model.Register(model.TypeHarborSBOM, New) +} diff --git a/src/pkg/accessory/model/sbom/sbom_test.go b/src/pkg/accessory/model/sbom/sbom_test.go new file mode 100644 index 000000000..92f9bda27 --- /dev/null +++ b/src/pkg/accessory/model/sbom/sbom_test.go @@ -0,0 +1,87 @@ +// Copyright Project Harbor Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package sbom + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/goharbor/harbor/src/pkg/accessory/model" + htesting "github.com/goharbor/harbor/src/testing" +) + +type SBOMTestSuite struct { + htesting.Suite + accessory model.Accessory + digest string + subDigest string +} + +func (suite *SBOMTestSuite) SetupSuite() { + suite.digest = suite.DigestString() + suite.subDigest = suite.DigestString() + suite.accessory, _ = model.New(model.TypeHarborSBOM, + model.AccessoryData{ + ArtifactID: 1, + SubArtifactDigest: suite.subDigest, + Size: 4321, + Digest: suite.digest, + }) +} + +func (suite *SBOMTestSuite) TestGetID() { + suite.Equal(int64(0), suite.accessory.GetData().ID) +} + +func (suite *SBOMTestSuite) TestGetArtID() { + suite.Equal(int64(1), suite.accessory.GetData().ArtifactID) +} + +func (suite *SBOMTestSuite) TestSubGetArtID() { + suite.Equal(suite.subDigest, suite.accessory.GetData().SubArtifactDigest) +} + +func (suite *SBOMTestSuite) TestSubGetSize() { + suite.Equal(int64(4321), suite.accessory.GetData().Size) +} + +func (suite *SBOMTestSuite) TestSubGetDigest() { + suite.Equal(suite.digest, suite.accessory.GetData().Digest) +} + +func (suite *SBOMTestSuite) TestSubGetType() { + suite.Equal(model.TypeHarborSBOM, suite.accessory.GetData().Type) +} + +func (suite *SBOMTestSuite) TestSubGetRefType() { + suite.Equal(model.RefHard, suite.accessory.Kind()) +} + +func (suite *SBOMTestSuite) TestIsSoft() { + suite.False(suite.accessory.IsSoft()) +} + +func (suite *SBOMTestSuite) TestIsHard() { + suite.True(suite.accessory.IsHard()) +} + +func (suite *SBOMTestSuite) TestDisplay() { + suite.False(suite.accessory.Display()) +} + +func TestSBOMTestSuite(t *testing.T) { + suite.Run(t, new(SBOMTestSuite)) +} diff --git a/src/server/middleware/subject/subject.go b/src/server/middleware/subject/subject.go index c4b86863e..4c1c47315 100644 --- a/src/server/middleware/subject/subject.go +++ b/src/server/middleware/subject/subject.go @@ -41,6 +41,9 @@ var ( // annotation of nydus image layerAnnotationNydusBootstrap = "containerd.io/snapshot/nydus-bootstrap" + + // media type of harbor sbom + mediaTypeHarborSBOM = "application/vnd.goharbor.harbor.sbom.v1" ) /* @@ -149,6 +152,8 @@ func Middleware() func(http.Handler) http.Handler { } case mediaTypeNotationLayer: accData.Type = model.TypeNotationSignature + case mediaTypeHarborSBOM: + accData.Type = model.TypeHarborSBOM } if subjectArt != nil { accData.SubArtifactID = subjectArt.ID