The tag retention job failed with 403 error message (#22159)
Build Package Workflow / BUILD_PACKAGE (push) Has been cancelled Details
Code scanning - action / CodeQL-Build (push) Has been cancelled Details
Housekeeping - Close stale issues and PRs / stale (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (harbor-core, dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (harbor-core, v2.12.0-dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (harbor-db, dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (harbor-db, v2.12.0-dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (harbor-exporter, dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (harbor-exporter, v2.12.0-dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (harbor-jobservice, dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (harbor-jobservice, v2.12.0-dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (harbor-log, dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (harbor-log, v2.12.0-dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (harbor-portal, dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (harbor-portal, v2.12.0-dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (harbor-registryctl, dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (harbor-registryctl, v2.12.0-dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (prepare, dev) (push) Has been cancelled Details
Trivy Nightly Scan / Trivy Scan nightly (prepare, v2.12.0-dev) (push) Has been cancelled Details
CONFORMANCE_TEST / CONFORMANCE_TEST (push) Has been cancelled Details

fixes #22141

Signed-off-by: stonezdj <stone.zhang@broadcom.com>
This commit is contained in:
stonezdj(Daojun Zhang) 2025-07-31 14:43:00 +08:00 committed by GitHub
parent 70b03c9483
commit 6a1abab687
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 44 additions and 54 deletions

View File

@ -49,17 +49,17 @@ type auditlogAPI struct {
projectCtl project.Controller projectCtl project.Controller
} }
func (a *auditlogAPI) ListAuditLogs(ctx context.Context, params auditlog.ListAuditLogsParams) middleware.Responder { func (a *auditlogAPI) checkPermissionAndBuildQuery(ctx context.Context, qs *string, sort *string, page *int64, pageSize *int64) (*q.Query, error) {
secCtx, ok := security.FromContext(ctx) secCtx, ok := security.FromContext(ctx)
if !ok { if !ok {
return a.SendError(ctx, errors.UnauthorizedError(errors.New("security context not found"))) return nil, errors.UnauthorizedError(errors.New("security context not found"))
} }
if !secCtx.IsAuthenticated() { if !secCtx.IsAuthenticated() {
return a.SendError(ctx, errors.UnauthorizedError(nil).WithMessage(secCtx.GetUsername())) return nil, errors.UnauthorizedError(nil).WithMessage(secCtx.GetUsername())
} }
query, err := a.BuildQuery(ctx, params.Q, params.Sort, params.Page, params.PageSize) query, err := a.BuildQuery(ctx, qs, sort, page, pageSize)
if err != nil { if err != nil {
return a.SendError(ctx, err) return nil, err
} }
if err := a.RequireSystemAccess(ctx, rbac.ActionList, rbac.ResourceAuditLog); err != nil { if err := a.RequireSystemAccess(ctx, rbac.ActionList, rbac.ResourceAuditLog); err != nil {
@ -73,11 +73,16 @@ func (a *auditlogAPI) ListAuditLogs(ctx context.Context, params auditlog.ListAud
projects, err := a.projectCtl.List(ctx, q.New(q.KeyWords{"member": member}), project.Metadata(false)) projects, err := a.projectCtl.List(ctx, q.New(q.KeyWords{"member": member}), project.Metadata(false))
if err != nil { if err != nil {
return a.SendError(ctx, fmt.Errorf( return nil, errors.Errorf(
"failed to get projects of user %s: %v", secCtx.GetUsername(), err)) "failed to get projects of user %s: %v", secCtx.GetUsername(), err)
} }
for _, project := range projects { for _, project := range projects {
if a.HasProjectPermission(ctx, project.ProjectID, rbac.ActionList, rbac.ResourceLog) { hasPerm, err := a.HasProjectPermission(ctx, project.ProjectID, rbac.ActionList, rbac.ResourceLog)
if err != nil {
return nil, fmt.Errorf(
"failed to get project permission of user %s: %v", secCtx.GetUsername(), err)
}
if hasPerm {
ol.Values = append(ol.Values, project.ProjectID) ol.Values = append(ol.Values, project.ProjectID)
} }
} }
@ -88,6 +93,14 @@ func (a *auditlogAPI) ListAuditLogs(ctx context.Context, params auditlog.ListAud
} }
query.Keywords["ProjectID"] = ol query.Keywords["ProjectID"] = ol
} }
return query, nil
}
func (a *auditlogAPI) ListAuditLogs(ctx context.Context, params auditlog.ListAuditLogsParams) middleware.Responder {
query, err := a.checkPermissionAndBuildQuery(ctx, params.Q, params.Sort, params.Page, params.PageSize)
if err != nil {
return a.SendError(ctx, err)
}
total, err := a.auditMgr.Count(ctx, query) total, err := a.auditMgr.Count(ctx, query)
if err != nil { if err != nil {
@ -114,46 +127,13 @@ func (a *auditlogAPI) ListAuditLogs(ctx context.Context, params auditlog.ListAud
WithLink(a.Links(ctx, params.HTTPRequest.URL, total, query.PageNumber, query.PageSize).String()). WithLink(a.Links(ctx, params.HTTPRequest.URL, total, query.PageNumber, query.PageSize).String()).
WithPayload(auditLogs) WithPayload(auditLogs)
} }
func (a *auditlogAPI) ListAuditLogExts(ctx context.Context, params auditlog.ListAuditLogExtsParams) middleware.Responder { func (a *auditlogAPI) ListAuditLogExts(ctx context.Context, params auditlog.ListAuditLogExtsParams) middleware.Responder {
secCtx, ok := security.FromContext(ctx) query, err := a.checkPermissionAndBuildQuery(ctx, params.Q, params.Sort, params.Page, params.PageSize)
if !ok {
return a.SendError(ctx, errors.UnauthorizedError(errors.New("security context not found")))
}
if !secCtx.IsAuthenticated() {
return a.SendError(ctx, errors.UnauthorizedError(nil).WithMessage(secCtx.GetUsername()))
}
query, err := a.BuildQuery(ctx, params.Q, params.Sort, params.Page, params.PageSize)
if err != nil { if err != nil {
return a.SendError(ctx, err) return a.SendError(ctx, err)
} }
if err := a.RequireSystemAccess(ctx, rbac.ActionList, rbac.ResourceAuditLog); err != nil {
ol := &q.OrList{}
if sc, ok := secCtx.(*local.SecurityContext); ok && sc.IsAuthenticated() {
user := sc.User()
member := &project.MemberQuery{
UserID: user.UserID,
GroupIDs: user.GroupIDs,
}
projects, err := a.projectCtl.List(ctx, q.New(q.KeyWords{"member": member}), project.Metadata(false))
if err != nil {
return a.SendError(ctx, fmt.Errorf(
"failed to get projects of user %s: %v", secCtx.GetUsername(), err))
}
for _, project := range projects {
if a.HasProjectPermission(ctx, project.ProjectID, rbac.ActionList, rbac.ResourceLog) {
ol.Values = append(ol.Values, project.ProjectID)
}
}
}
// make sure no project will be selected with the query
if len(ol.Values) == 0 {
ol.Values = append(ol.Values, -1)
}
query.Keywords["ProjectID"] = ol
}
total, err := a.auditextMgr.Count(ctx, query) total, err := a.auditextMgr.Count(ctx, query)
if err != nil { if err != nil {
return a.SendError(ctx, err) return a.SendError(ctx, err)

View File

@ -74,11 +74,11 @@ func (b *BaseAPI) HasPermission(ctx context.Context, action rbac.Action, resourc
return s.Can(ctx, action, resource) return s.Can(ctx, action, resource)
} }
// HasProjectPermission returns true when the request has action permission on project subresource // HasProjectPermission returns true, nil when the request has action permission on project subresource, and return false, error when the request does not have permission or an error occurs.
func (b *BaseAPI) HasProjectPermission(ctx context.Context, projectIDOrName any, action rbac.Action, subresource ...rbac.Resource) bool { func (b *BaseAPI) HasProjectPermission(ctx context.Context, projectIDOrName any, action rbac.Action, subresource ...rbac.Resource) (bool, error) {
projectID, projectName, err := utils.ParseProjectIDOrName(projectIDOrName) projectID, projectName, err := utils.ParseProjectIDOrName(projectIDOrName)
if err != nil { if err != nil {
return false return false, err
} }
if projectName != "" { if projectName != "" {
@ -88,25 +88,29 @@ func (b *BaseAPI) HasProjectPermission(ctx context.Context, projectIDOrName any,
if errors.IsNotFoundErr(err) { if errors.IsNotFoundErr(err) {
p = &project.Project{} p = &project.Project{}
} else { } else {
return false return false, err
} }
} }
if p == nil { if p == nil {
log.Warningf("project %s not found", projectName) log.Warningf("project %s not found", projectName)
return false return false, nil
} }
projectID = p.ProjectID projectID = p.ProjectID
} }
resource := rbac_project.NewNamespace(projectID).Resource(subresource...) resource := rbac_project.NewNamespace(projectID).Resource(subresource...)
return b.HasPermission(ctx, action, resource) return b.HasPermission(ctx, action, resource), nil
} }
// RequireProjectAccess checks the permission against the resources according to the context // RequireProjectAccess checks the permission against the resources according to the context
// An error will be returned if it doesn't meet the requirement // An error will be returned if it doesn't meet the requirement
func (b *BaseAPI) RequireProjectAccess(ctx context.Context, projectIDOrName any, action rbac.Action, subresource ...rbac.Resource) error { func (b *BaseAPI) RequireProjectAccess(ctx context.Context, projectIDOrName any, action rbac.Action, subresource ...rbac.Resource) error {
if b.HasProjectPermission(ctx, projectIDOrName, action, subresource...) { has, err := b.HasProjectPermission(ctx, projectIDOrName, action, subresource...)
if err != nil {
return err
}
if has {
return nil return nil
} }
secCtx, err := b.GetSecurityContext(ctx) secCtx, err := b.GetSecurityContext(ctx)

View File

@ -387,12 +387,18 @@ func (a *projectAPI) GetProjectSummary(ctx context.Context, params operation.Get
} }
var fetchSummaries []func(context.Context, *project.Project, *models.ProjectSummary) var fetchSummaries []func(context.Context, *project.Project, *models.ProjectSummary)
hasPerm, err := a.HasProjectPermission(ctx, p.ProjectID, rbac.ActionRead, rbac.ResourceQuota)
if hasPerm := a.HasProjectPermission(ctx, p.ProjectID, rbac.ActionRead, rbac.ResourceQuota); hasPerm { if err != nil {
return a.SendError(ctx, err)
}
if hasPerm {
fetchSummaries = append(fetchSummaries, getProjectQuotaSummary) fetchSummaries = append(fetchSummaries, getProjectQuotaSummary)
} }
hasPerm, err = a.HasProjectPermission(ctx, p.ProjectID, rbac.ActionList, rbac.ResourceMember)
if hasPerm := a.HasProjectPermission(ctx, p.ProjectID, rbac.ActionList, rbac.ResourceMember); hasPerm { if err != nil {
return a.SendError(ctx, err)
}
if hasPerm {
fetchSummaries = append(fetchSummaries, a.getProjectMemberSummary) fetchSummaries = append(fetchSummaries, a.getProjectMemberSummary)
} }