fix cosign conflict error on landing data (#16228)

Cosign client will generate the same signature to the same manifest, ignore the conflict error in middleware

Signed-off-by: Wang Yan <wangyan@vmware.com>
This commit is contained in:
Wang Yan 2022-01-17 19:09:56 +08:00 committed by GitHub
parent 01c6f6084b
commit 0b4f98074e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 9 deletions

View File

@ -1,12 +1,14 @@
package cosign
import (
"context"
"fmt"
"github.com/docker/distribution/reference"
"github.com/goharbor/harbor/src/controller/artifact"
"github.com/goharbor/harbor/src/lib"
"github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/lib/log"
"github.com/goharbor/harbor/src/lib/orm"
"github.com/goharbor/harbor/src/pkg/accessory"
"github.com/goharbor/harbor/src/pkg/accessory/model"
"github.com/goharbor/harbor/src/pkg/distribution"
@ -104,16 +106,20 @@ func CosignSignatureMiddleware() func(http.Handler) http.Handler {
return err
}
_, err = accessory.Mgr.Create(ctx, model.AccessoryData{
ArtifactID: art.ID,
SubArtifactID: subjectArt.ID,
Size: desc.Size,
Digest: desc.Digest.String(),
Type: model.TypeCosignSignature,
})
if err != nil {
logger.Errorf("failed to get cosign signature artifact: %s, error: %v", desc.Digest.String(), err)
if err := orm.WithTransaction(func(ctx context.Context) error {
_, err := accessory.Mgr.Create(ctx, model.AccessoryData{
ArtifactID: art.ID,
SubArtifactID: subjectArt.ID,
Size: desc.Size,
Digest: desc.Digest.String(),
Type: model.TypeCosignSignature,
})
return err
})(orm.SetTransactionOpNameToContext(ctx, "tx-create-cosign-accessory")); err != nil {
if !errors.IsConflictErr(err) {
logger.Errorf("failed to create cosign signature artifact: %s, error: %v", desc.Digest.String(), err)
return err
}
}
}

View File

@ -7,6 +7,7 @@ import (
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/pkg/accessory"
"github.com/goharbor/harbor/src/pkg/accessory/model"
accessorymodel "github.com/goharbor/harbor/src/pkg/accessory/model"
"github.com/goharbor/harbor/src/pkg/artifact"
"github.com/goharbor/harbor/src/pkg/distribution"
htesting "github.com/goharbor/harbor/src/testing"
@ -81,6 +82,44 @@ func (suite *MiddlewareTestSuite) addArt(pid, repositoryID int64, repositoryName
return afid
}
func (suite *MiddlewareTestSuite) addArtAcc(pid, repositoryID int64, repositoryName, dgt, accdgt string) int64 {
subaf := &artifact.Artifact{
Type: "Docker-Image",
ProjectID: pid,
RepositoryID: repositoryID,
RepositoryName: repositoryName,
Digest: dgt,
Size: 1024,
PushTime: time.Now(),
PullTime: time.Now(),
}
subafid, err := artifact.Mgr.Create(suite.Context(), subaf)
suite.Nil(err, fmt.Sprintf("Add artifact failed for %d", repositoryID))
af := &artifact.Artifact{
Type: "Cosign",
ProjectID: pid,
RepositoryID: repositoryID,
RepositoryName: repositoryName,
Digest: accdgt,
Size: 1024,
PushTime: time.Now(),
PullTime: time.Now(),
}
afid, err := artifact.Mgr.Create(suite.Context(), af)
suite.Nil(err, fmt.Sprintf("Add artifact failed for %d", repositoryID))
accid, err := accessory.Mgr.Create(suite.Context(), accessorymodel.AccessoryData{
ID: 1,
ArtifactID: afid,
SubArtifactID: subafid,
Digest: accdgt,
Type: accessorymodel.TypeCosignSignature,
})
suite.Nil(err, fmt.Sprintf("Add artifact accesspry failed for %d", repositoryID))
return accid
}
func (suite *MiddlewareTestSuite) TestCosignSignature() {
suite.WithProject(func(projectID int64, projectName string) {
name := fmt.Sprintf("%s/hello-world", projectName)
@ -112,6 +151,34 @@ func (suite *MiddlewareTestSuite) TestCosignSignature() {
})
}
func (suite *MiddlewareTestSuite) TestCosignSignatureDup() {
suite.WithProject(func(projectID int64, projectName string) {
name := fmt.Sprintf("%s/hello-world", projectName)
subArtDigest := suite.DigestString()
ref := fmt.Sprintf("%s.sig", strings.ReplaceAll(subArtDigest, "sha256:", "sha256-"))
_, descriptor, req := suite.prepare(name, ref)
_, repoId, err := repository.Ctl.Ensure(suite.Context(), name)
suite.Nil(err)
accID := suite.addArtAcc(projectID, repoId, name, subArtDigest, descriptor.Digest.String())
res := httptest.NewRecorder()
next := suite.NextHandler(http.StatusCreated, map[string]string{"Docker-Content-Digest": descriptor.Digest.String()})
CosignSignatureMiddleware()(next).ServeHTTP(res, req)
suite.Equal(http.StatusCreated, res.Code)
accs, err := accessory.Mgr.List(suite.Context(), &q.Query{
Keywords: map[string]interface{}{
"ID": accID,
},
})
suite.Equal(1, len(accs))
suite.Equal(descriptor.Digest.String(), accs[0].GetData().Digest)
suite.True(accs[0].IsHard())
suite.Equal(model.TypeCosignSignature, accs[0].GetData().Type)
})
}
func (suite *MiddlewareTestSuite) TestMatchManifestURLPattern() {
_, _, ok := matchCosignSignaturePattern("/v2/library/hello-world/manifests/.Invalid")
suite.False(ok)