Fix the update of retention policy (#17238)

Signed-off-by: stonezdj <stonezdj@gmail.com>

Co-authored-by: Wang Yan <wangyan@vmware.com>
This commit is contained in:
stonezdj(Daojun Zhang) 2022-07-27 01:11:02 +08:00 committed by GitHub
parent d91706b5fd
commit eff9118591
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 10 deletions

View File

@ -305,6 +305,7 @@ func convertExecution(exec *task.Execution) *retention.Execution {
Status: exec.Status,
Trigger: exec.Trigger,
DryRun: exec.ExtraAttrs["dry_run"].(bool),
Type: exec.VendorType,
}
}

View File

@ -39,6 +39,7 @@ type Execution struct {
Status string `json:"status"`
Trigger string `json:"trigger"`
DryRun bool `json:"dry_run"`
Type string `json:"-"`
}
// Task of retention

View File

@ -11,6 +11,7 @@ import (
"github.com/goharbor/harbor/src/common/rbac"
projectCtl "github.com/goharbor/harbor/src/controller/project"
retentionCtl "github.com/goharbor/harbor/src/controller/retention"
"github.com/goharbor/harbor/src/jobservice/job"
"github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/pkg/project/metadata"
"github.com/goharbor/harbor/src/pkg/retention/policy"
@ -202,12 +203,14 @@ func (r *retentionAPI) UpdateRetention(ctx context.Context, params operation.Upd
if err := r.checkRuleConflict(p); err != nil {
return r.SendError(ctx, errors.ConflictError(err))
}
err := r.requireAccess(ctx, p, rbac.ActionUpdate)
if err != nil {
if err := r.requireAccess(ctx, p, rbac.ActionUpdate); err != nil {
return r.SendError(ctx, err)
}
if err := r.requirePolicyAccess(ctx, p); err != nil {
return r.SendError(ctx, err)
}
if err = r.retentionCtl.UpdateRetention(ctx, p); err != nil {
if err := r.retentionCtl.UpdateRetention(ctx, p); err != nil {
return r.SendError(ctx, err)
}
return operation.NewUpdateRetentionOK()
@ -270,11 +273,19 @@ func (r *retentionAPI) OperateRetentionExecution(ctx context.Context, params ope
if err != nil {
return r.SendError(ctx, errors.BadRequestError(err))
}
err = r.requireAccess(ctx, p, rbac.ActionUpdate)
if err != nil {
if p == nil {
return r.SendError(ctx, errors.New("retention policy is not found").WithCode(errors.NotFoundCode))
}
if err := r.requireAccess(ctx, p, rbac.ActionUpdate); err != nil {
return r.SendError(ctx, err)
}
if err = r.retentionCtl.OperateRetentionExec(ctx, params.Eid, params.Body.Action); err != nil {
if err := r.requirePolicyAccess(ctx, p); err != nil {
return r.SendError(ctx, err)
}
if err := r.requireExecutionInProject(ctx, p, params.Eid); err != nil {
return r.SendError(ctx, err)
}
if err := r.retentionCtl.OperateRetentionExec(ctx, params.Eid, params.Body.Action); err != nil {
return r.SendError(ctx, err)
}
return operation.NewOperateRetentionExecutionOK()
@ -319,8 +330,16 @@ func (r *retentionAPI) ListRetentionTasks(ctx context.Context, params operation.
if err != nil {
return r.SendError(ctx, errors.BadRequestError(err))
}
err = r.requireAccess(ctx, p, rbac.ActionList)
if err != nil {
if p == nil {
return r.SendError(ctx, errors.New("retention policy is not found").WithCode(errors.NotFoundCode))
}
if err := r.requireAccess(ctx, p, rbac.ActionList); err != nil {
return r.SendError(ctx, err)
}
if err := r.requirePolicyAccess(ctx, p); err != nil {
return r.SendError(ctx, err)
}
if err := r.requireExecutionInProject(ctx, p, params.Eid); err != nil {
return r.SendError(ctx, err)
}
tasks, err := r.retentionCtl.ListRetentionExecTasks(ctx, params.Eid, query)
@ -345,8 +364,16 @@ func (r *retentionAPI) GetRetentionTaskLog(ctx context.Context, params operation
if err != nil {
return r.SendError(ctx, errors.BadRequestError(err))
}
err = r.requireAccess(ctx, p, rbac.ActionRead)
if err != nil {
if p == nil {
return r.SendError(ctx, errors.New("retention policy is not found").WithCode(errors.NotFoundCode))
}
if err := r.requireAccess(ctx, p, rbac.ActionRead); err != nil {
return r.SendError(ctx, err)
}
if err := r.requirePolicyAccess(ctx, p); err != nil {
return r.SendError(ctx, err)
}
if err := r.requireTaskInProject(ctx, p, params.Eid, params.Tid); err != nil {
return r.SendError(ctx, err)
}
@ -368,3 +395,56 @@ func (r *retentionAPI) requireAccess(ctx context.Context, p *policy.Metadata, ac
}
return r.RequireSystemAccess(ctx, action, rbac.ResourceTagRetention)
}
// requirePolicyAccess checks the scope reference whether has the permission to
// the retention policy.
func (r *retentionAPI) requirePolicyAccess(ctx context.Context, p *policy.Metadata) error {
// the id of policy should be consistent with project metadata
meta, err := r.proMetaMgr.Get(ctx, p.Scope.Reference, "retention_id")
if err != nil {
return err
}
// validate
if len(meta["retention_id"]) > 0 {
// return err if retention id does not match
if meta["retention_id"] == fmt.Sprintf("%d", p.ID) {
return nil
}
}
return errors.NotFoundError(errors.Errorf("the retention policy id %d does not match", p.ID))
}
func (r *retentionAPI) requireExecutionInProject(ctx context.Context, p *policy.Metadata, executionID int64) error {
exec, err := r.retentionCtl.GetRetentionExec(ctx, executionID)
if err != nil {
return err
}
if exec == nil {
return errors.New(nil).WithMessage("project: %d, execution id %d not found", p.Scope.Reference, executionID).WithCode(errors.NotFoundCode)
}
if exec.PolicyID != p.ID {
return errors.New(nil).WithMessage("project: %d, execution id %d not found", p.Scope.Reference, executionID).WithCode(errors.NotFoundCode)
}
if exec.Type != job.Retention {
return errors.New(nil).WithMessage("project: %d, execution id %d not found", p.Scope.Reference, executionID).WithCode(errors.NotFoundCode)
}
return nil
}
func (r *retentionAPI) requireTaskInProject(ctx context.Context, p *policy.Metadata, executionID, taskID int64) error {
if err := r.requireExecutionInProject(ctx, p, executionID); err != nil {
return err
}
task, err := r.retentionCtl.GetRetentionExecTask(ctx, taskID)
if err != nil {
return err
}
if task == nil {
return errors.New(nil).WithMessage("project: %d, execution id %d not found", p.Scope.Reference, executionID).WithCode(errors.NotFoundCode)
}
if task.ExecutionID != executionID {
return errors.New(nil).WithMessage("project: %d, execution id %d not found", p.Scope.Reference, executionID).WithCode(errors.NotFoundCode)
}
return nil
}