diff --git a/api/v2.0/swagger.yaml b/api/v2.0/swagger.yaml index 1f06b719266..f551ae671a8 100644 --- a/api/v2.0/swagger.yaml +++ b/api/v2.0/swagger.yaml @@ -7888,6 +7888,9 @@ definitions: job_status: type: string description: the status of gc job. + job_id: + type: string + description: the id of gc job. deleted: type: boolean description: if gc job was deleted. diff --git a/src/server/middleware/contenttrust/contentrust.go b/src/server/middleware/contenttrust/contentrust.go index 28003dbc930..e3eabcdc156 100644 --- a/src/server/middleware/contenttrust/contentrust.go +++ b/src/server/middleware/contenttrust/contentrust.go @@ -46,11 +46,17 @@ func ContentTrust() func(http.Handler) http.Handler { // If signature policy enabled, it has to at least have one signature. if pro.ContentTrustCosignEnabled() { if err := signatureChecking(ctx, r, af, pro.ProjectID, model.TypeCosignSignature); err != nil { + if errors.IsErr(err, errors.PROJECTPOLICYVIOLATION) { + return errors.New(nil).WithCode(errors.PROJECTPOLICYVIOLATION).WithMessage("The image is not signed by cosign.") + } return err } } if pro.ContentTrustEnabled() { if err := signatureChecking(ctx, r, af, pro.ProjectID, model.TypeNotationSignature); err != nil { + if errors.IsErr(err, errors.PROJECTPOLICYVIOLATION) { + return errors.New(nil).WithCode(errors.PROJECTPOLICYVIOLATION).WithMessage("The image is not signed by notation.") + } return err } } @@ -78,8 +84,7 @@ func signatureChecking(ctx context.Context, r *http.Request, af lib.ArtifactInfo } if len(art.Accessories) == 0 { - pkgE := errors.New(nil).WithCode(errors.PROJECTPOLICYVIOLATION).WithMessage("The image is not signed.") - return pkgE + return errors.New(nil).WithCode(errors.PROJECTPOLICYVIOLATION) } var hasSignature bool @@ -90,8 +95,7 @@ func signatureChecking(ctx context.Context, r *http.Request, af lib.ArtifactInfo } } if !hasSignature { - pkgE := errors.New(nil).WithCode(errors.PROJECTPOLICYVIOLATION).WithMessage("The image is not signed.") - return pkgE + return errors.New(nil).WithCode(errors.PROJECTPOLICYVIOLATION) } return nil diff --git a/src/server/v2.0/handler/gc.go b/src/server/v2.0/handler/gc.go index 7be005b9dfd..161f2b180ec 100644 --- a/src/server/v2.0/handler/gc.go +++ b/src/server/v2.0/handler/gc.go @@ -195,6 +195,17 @@ func (g *gcAPI) GetGCHistory(ctx context.Context, params operation.GetGCHistoryP if err != nil { return g.SendError(ctx, err) } + + tasks, err := g.gcCtr.ListTasks(ctx, q.New(q.KeyWords{ + "ExecutionID": exec.ID, + })) + if err != nil { + return g.SendError(ctx, err) + } + if len(tasks) == 0 { + return g.SendError(ctx, errors.New(nil).WithCode(errors.NotFoundCode).WithMessage("garbage collection %d log is not found", exec.ID)) + } + hs = append(hs, &model.GCHistory{ ID: exec.ID, Name: job.GarbageCollectionVendorType, @@ -203,6 +214,7 @@ func (g *gcAPI) GetGCHistory(ctx context.Context, params operation.GetGCHistoryP Schedule: &model.ScheduleParam{ Type: exec.Trigger, }, + JobID: tasks[0].JobID, Status: exec.Status, CreationTime: exec.StartTime, UpdateTime: exec.UpdateTime, @@ -234,6 +246,16 @@ func (g *gcAPI) GetGC(ctx context.Context, params operation.GetGCParams) middlew return g.SendError(ctx, err) } + tasks, err := g.gcCtr.ListTasks(ctx, q.New(q.KeyWords{ + "ExecutionID": params.GCID, + })) + if err != nil { + return g.SendError(ctx, err) + } + if len(tasks) == 0 { + return g.SendError(ctx, errors.New(nil).WithCode(errors.NotFoundCode).WithMessage("garbage collection %d log is not found", params.GCID)) + } + res := &model.GCHistory{ ID: exec.ID, Name: job.GarbageCollectionVendorType, @@ -243,6 +265,7 @@ func (g *gcAPI) GetGC(ctx context.Context, params operation.GetGCParams) middlew Schedule: &model.ScheduleParam{ Type: exec.Trigger, }, + JobID: tasks[0].JobID, CreationTime: exec.StartTime, UpdateTime: exec.UpdateTime, } diff --git a/src/server/v2.0/handler/model/gc.go b/src/server/v2.0/handler/model/gc.go index b0cb65ed478..99b1b8be68c 100644 --- a/src/server/v2.0/handler/model/gc.go +++ b/src/server/v2.0/handler/model/gc.go @@ -46,6 +46,7 @@ type GCHistory struct { Parameters string `json:"job_parameters"` Status string `json:"job_status"` UUID string `json:"-"` + JobID string `json:"job_id"` Deleted bool `json:"deleted"` CreationTime time.Time `json:"creation_time"` UpdateTime time.Time `json:"update_time"` @@ -60,6 +61,7 @@ func (h *GCHistory) ToSwagger() *models.GCHistory { JobParameters: h.Parameters, Deleted: h.Deleted, JobStatus: h.Status, + JobID: h.JobID, Schedule: &models.ScheduleObj{ // covert MANUAL to Manual because the type of the ScheduleObj // must be 'Hourly', 'Daily', 'Weekly', 'Custom', 'Manual' and 'None' diff --git a/tests/apitests/python/test_project_level_policy_content_trust.py b/tests/apitests/python/test_project_level_policy_content_trust.py index 002741e04c0..5e174de5ba5 100644 --- a/tests/apitests/python/test_project_level_policy_content_trust.py +++ b/tests/apitests/python/test_project_level_policy_content_trust.py @@ -84,7 +84,7 @@ def testProjectLevelPolicyContentTrust(self): restart_process("containerd") restart_process("dockerd") time.sleep(30) - pull_harbor_image(harbor_server, ADMIN_CLIENT["username"], ADMIN_CLIENT["password"], TestProjects.repo_name, tag, expected_error_message = "The image is not signed") + pull_harbor_image(harbor_server, ADMIN_CLIENT["username"], ADMIN_CLIENT["password"], TestProjects.repo_name, tag, expected_error_message = "The image is not signed by cosign") if __name__ == '__main__': unittest.main() diff --git a/tests/robot-cases/Group1-Nightly/Common.robot b/tests/robot-cases/Group1-Nightly/Common.robot index 50de09214ca..e892b211e0b 100644 --- a/tests/robot-cases/Group1-Nightly/Common.robot +++ b/tests/robot-cases/Group1-Nightly/Common.robot @@ -773,7 +773,7 @@ Test Case - Cosign And Cosign Deployment Security Policy Go Into Project project${d} Go Into Repo project${d} ${image} Should Not Be Signed By Cosign ${tag} - Cannot Pull Image ${ip} ${user} ${pwd} project${d} ${image}:${tag} err_msg=The image is not signed. + Cannot Pull Image ${ip} ${user} ${pwd} project${d} ${image}:${tag} err_msg=The image is not signed by cosign. Cosign Generate Key Pair Cosign Verify ${ip}/project${d}/${image}:${tag} ${false}