mirror of
https://github.com/goharbor/harbor.git
synced 2025-02-17 04:11:24 +01:00
permission grant for scanner related actions are not correctly
- add new endpoint for getting scanner candidates of specified project - adjust the permission granting functions - fix #9608 Signed-off-by: Steven Zou <szou@vmware.com>
This commit is contained in:
parent
5c4c04a122
commit
5b2ab34e03
@ -61,5 +61,6 @@ const (
|
|||||||
ResourceRobot = Resource("robot")
|
ResourceRobot = Resource("robot")
|
||||||
ResourceNotificationPolicy = Resource("notification-policy")
|
ResourceNotificationPolicy = Resource("notification-policy")
|
||||||
ResourceScan = Resource("scan")
|
ResourceScan = Resource("scan")
|
||||||
|
ResourceScanner = Resource("scanner")
|
||||||
ResourceSelf = Resource("") // subresource for self
|
ResourceSelf = Resource("") // subresource for self
|
||||||
)
|
)
|
||||||
|
@ -45,6 +45,9 @@ var (
|
|||||||
|
|
||||||
{Resource: rbac.ResourceHelmChartVersion, Action: rbac.ActionRead},
|
{Resource: rbac.ResourceHelmChartVersion, Action: rbac.ActionRead},
|
||||||
{Resource: rbac.ResourceHelmChartVersion, Action: rbac.ActionList},
|
{Resource: rbac.ResourceHelmChartVersion, Action: rbac.ActionList},
|
||||||
|
|
||||||
|
{Resource: rbac.ResourceScan, Action: rbac.ActionRead},
|
||||||
|
{Resource: rbac.ResourceScanner, Action: rbac.ActionRead},
|
||||||
}
|
}
|
||||||
|
|
||||||
// all policies for the projects
|
// all policies for the projects
|
||||||
|
@ -124,6 +124,9 @@ var (
|
|||||||
|
|
||||||
{Resource: rbac.ResourceScan, Action: rbac.ActionCreate},
|
{Resource: rbac.ResourceScan, Action: rbac.ActionCreate},
|
||||||
{Resource: rbac.ResourceScan, Action: rbac.ActionRead},
|
{Resource: rbac.ResourceScan, Action: rbac.ActionRead},
|
||||||
|
|
||||||
|
{Resource: rbac.ResourceScanner, Action: rbac.ActionRead},
|
||||||
|
{Resource: rbac.ResourceScanner, Action: rbac.ActionCreate},
|
||||||
},
|
},
|
||||||
|
|
||||||
"master": {
|
"master": {
|
||||||
@ -211,6 +214,8 @@ var (
|
|||||||
|
|
||||||
{Resource: rbac.ResourceScan, Action: rbac.ActionCreate},
|
{Resource: rbac.ResourceScan, Action: rbac.ActionCreate},
|
||||||
{Resource: rbac.ResourceScan, Action: rbac.ActionRead},
|
{Resource: rbac.ResourceScan, Action: rbac.ActionRead},
|
||||||
|
|
||||||
|
{Resource: rbac.ResourceScanner, Action: rbac.ActionRead},
|
||||||
},
|
},
|
||||||
|
|
||||||
"developer": {
|
"developer": {
|
||||||
@ -266,6 +271,8 @@ var (
|
|||||||
|
|
||||||
{Resource: rbac.ResourceScan, Action: rbac.ActionCreate},
|
{Resource: rbac.ResourceScan, Action: rbac.ActionCreate},
|
||||||
{Resource: rbac.ResourceScan, Action: rbac.ActionRead},
|
{Resource: rbac.ResourceScan, Action: rbac.ActionRead},
|
||||||
|
|
||||||
|
{Resource: rbac.ResourceScanner, Action: rbac.ActionRead},
|
||||||
},
|
},
|
||||||
|
|
||||||
"guest": {
|
"guest": {
|
||||||
@ -306,6 +313,10 @@ var (
|
|||||||
|
|
||||||
{Resource: rbac.ResourceRobot, Action: rbac.ActionRead},
|
{Resource: rbac.ResourceRobot, Action: rbac.ActionRead},
|
||||||
{Resource: rbac.ResourceRobot, Action: rbac.ActionList},
|
{Resource: rbac.ResourceRobot, Action: rbac.ActionList},
|
||||||
|
|
||||||
|
{Resource: rbac.ResourceScan, Action: rbac.ActionRead},
|
||||||
|
|
||||||
|
{Resource: rbac.ResourceScanner, Action: rbac.ActionRead},
|
||||||
},
|
},
|
||||||
|
|
||||||
"limitedGuest": {
|
"limitedGuest": {
|
||||||
@ -330,6 +341,10 @@ var (
|
|||||||
{Resource: rbac.ResourceHelmChartVersion, Action: rbac.ActionList},
|
{Resource: rbac.ResourceHelmChartVersion, Action: rbac.ActionList},
|
||||||
|
|
||||||
{Resource: rbac.ResourceConfiguration, Action: rbac.ActionRead},
|
{Resource: rbac.ResourceConfiguration, Action: rbac.ActionRead},
|
||||||
|
|
||||||
|
{Resource: rbac.ResourceScan, Action: rbac.ActionRead},
|
||||||
|
|
||||||
|
{Resource: rbac.ResourceScanner, Action: rbac.ActionRead},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -217,6 +217,7 @@ func init() {
|
|||||||
// Add routes for project level scanner
|
// Add routes for project level scanner
|
||||||
proScannerAPI := &ProjectScannerAPI{}
|
proScannerAPI := &ProjectScannerAPI{}
|
||||||
beego.Router("/api/projects/:pid([0-9]+)/scanner", proScannerAPI, "get:GetProjectScanner;put:SetProjectScanner")
|
beego.Router("/api/projects/:pid([0-9]+)/scanner", proScannerAPI, "get:GetProjectScanner;put:SetProjectScanner")
|
||||||
|
beego.Router("/api/projects/:pid([0-9]+)/scanner/candidates", proScannerAPI, "get:GetProScannerCandidates")
|
||||||
|
|
||||||
// Add routes for scan
|
// Add routes for scan
|
||||||
scanAPI := &ScanAPI{}
|
scanAPI := &ScanAPI{}
|
||||||
|
@ -16,6 +16,7 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/goharbor/harbor/src/common/rbac"
|
"github.com/goharbor/harbor/src/common/rbac"
|
||||||
|
"github.com/goharbor/harbor/src/pkg/q"
|
||||||
"github.com/goharbor/harbor/src/pkg/scan/api/scanner"
|
"github.com/goharbor/harbor/src/pkg/scan/api/scanner"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -67,7 +68,7 @@ func (sa *ProjectScannerAPI) Prepare() {
|
|||||||
// GetProjectScanner gets the project level scanner
|
// GetProjectScanner gets the project level scanner
|
||||||
func (sa *ProjectScannerAPI) GetProjectScanner() {
|
func (sa *ProjectScannerAPI) GetProjectScanner() {
|
||||||
// Check access permissions
|
// Check access permissions
|
||||||
if !sa.RequireProjectAccess(sa.pid, rbac.ActionRead, rbac.ResourceConfiguration) {
|
if !sa.RequireProjectAccess(sa.pid, rbac.ActionRead, rbac.ResourceScanner) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,7 +90,7 @@ func (sa *ProjectScannerAPI) GetProjectScanner() {
|
|||||||
// SetProjectScanner sets the project level scanner
|
// SetProjectScanner sets the project level scanner
|
||||||
func (sa *ProjectScannerAPI) SetProjectScanner() {
|
func (sa *ProjectScannerAPI) SetProjectScanner() {
|
||||||
// Check access permissions
|
// Check access permissions
|
||||||
if !sa.RequireProjectAccess(sa.pid, rbac.ActionUpdate, rbac.ResourceConfiguration) {
|
if !sa.RequireProjectAccess(sa.pid, rbac.ActionCreate, rbac.ResourceScanner) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,3 +111,33 @@ func (sa *ProjectScannerAPI) SetProjectScanner() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetProScannerCandidates gets the candidates for setting project level scanner.
|
||||||
|
func (sa *ProjectScannerAPI) GetProScannerCandidates() {
|
||||||
|
// Check access permissions
|
||||||
|
// Same permission with project level scanner set action
|
||||||
|
if !sa.RequireProjectAccess(sa.pid, rbac.ActionCreate, rbac.ResourceScanner) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
p, pz, err := sa.GetPaginationParams()
|
||||||
|
if err != nil {
|
||||||
|
sa.SendBadRequestError(errors.Wrap(err, "scanner API: get project scanner candidates"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
query := &q.Query{
|
||||||
|
PageSize: pz,
|
||||||
|
PageNumber: p,
|
||||||
|
}
|
||||||
|
|
||||||
|
all, err := sa.c.ListRegistrations(query)
|
||||||
|
if err != nil {
|
||||||
|
sa.SendInternalServerError(errors.Wrap(err, "scanner API: get project scanner candidates"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response to the client
|
||||||
|
sa.Data["json"] = all
|
||||||
|
sa.ServeJSON()
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/goharbor/harbor/src/pkg/q"
|
||||||
"github.com/goharbor/harbor/src/pkg/scan/dao/scanner"
|
"github.com/goharbor/harbor/src/pkg/scan/dao/scanner"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -93,3 +94,33 @@ func (suite *ProScannerAPITestSuite) TestScannerAPIProjectScanner() {
|
|||||||
assert.Equal(suite.T(), r.Name, rr.Name)
|
assert.Equal(suite.T(), r.Name, rr.Name)
|
||||||
assert.Equal(suite.T(), r.UUID, rr.UUID)
|
assert.Equal(suite.T(), r.UUID, rr.UUID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestScannerAPIGetScannerCandidates ...
|
||||||
|
func (suite *ProScannerAPITestSuite) TestScannerAPIGetScannerCandidates() {
|
||||||
|
query := &q.Query{
|
||||||
|
PageNumber: 1,
|
||||||
|
PageSize: 500,
|
||||||
|
}
|
||||||
|
|
||||||
|
ll := []*scanner.Registration{
|
||||||
|
{
|
||||||
|
ID: 1005,
|
||||||
|
UUID: "uuid",
|
||||||
|
Name: "TestScannerAPIGetScannerCandidates",
|
||||||
|
Description: "JUST FOR TEST",
|
||||||
|
URL: "https://a.b.c",
|
||||||
|
}}
|
||||||
|
suite.mockC.On("ListRegistrations", query).Return(ll, nil)
|
||||||
|
|
||||||
|
// Get
|
||||||
|
l := make([]*scanner.Registration, 0)
|
||||||
|
err := handleAndParse(&testingRequest{
|
||||||
|
url: fmt.Sprintf("/api/projects/%d/scanner/candidates", 1),
|
||||||
|
method: http.MethodGet,
|
||||||
|
credential: projAdmin,
|
||||||
|
}, &l)
|
||||||
|
require.NoError(suite.T(), err)
|
||||||
|
|
||||||
|
assert.Equal(suite.T(), 1, len(l))
|
||||||
|
assert.Equal(suite.T(), "uuid", l[0].UUID)
|
||||||
|
}
|
||||||
|
@ -204,6 +204,7 @@ func initRouters() {
|
|||||||
// Add routes for project level scanner
|
// Add routes for project level scanner
|
||||||
proScannerAPI := &api.ProjectScannerAPI{}
|
proScannerAPI := &api.ProjectScannerAPI{}
|
||||||
beego.Router("/api/projects/:pid([0-9]+)/scanner", proScannerAPI, "get:GetProjectScanner;put:SetProjectScanner")
|
beego.Router("/api/projects/:pid([0-9]+)/scanner", proScannerAPI, "get:GetProjectScanner;put:SetProjectScanner")
|
||||||
|
beego.Router("/api/projects/:pid([0-9]+)/scanner/candidates", proScannerAPI, "get:GetProScannerCandidates")
|
||||||
|
|
||||||
// Add routes for scan
|
// Add routes for scan
|
||||||
scanAPI := &api.ScanAPI{}
|
scanAPI := &api.ScanAPI{}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
package scanner
|
package scanner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/goharbor/harbor/src/common/utils/log"
|
||||||
"github.com/goharbor/harbor/src/core/promgr/metamgr"
|
"github.com/goharbor/harbor/src/core/promgr/metamgr"
|
||||||
"github.com/goharbor/harbor/src/jobservice/logger"
|
"github.com/goharbor/harbor/src/jobservice/logger"
|
||||||
"github.com/goharbor/harbor/src/pkg/q"
|
"github.com/goharbor/harbor/src/pkg/q"
|
||||||
@ -26,6 +27,8 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
proScannerMetaKey = "projectScanner"
|
proScannerMetaKey = "projectScanner"
|
||||||
|
statusUnhealthy = "unhealthy"
|
||||||
|
statusHealthy = "healthy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultController is a singleton api controller for plug scanners
|
// DefaultController is a singleton api controller for plug scanners
|
||||||
@ -214,6 +217,25 @@ func (bc *basicController) GetRegistrationByProject(projectID int64) (*scanner.R
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No scanner configured
|
||||||
|
if registration == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get metadata of the configured registration
|
||||||
|
meta, err := bc.Ping(registration)
|
||||||
|
if err != nil {
|
||||||
|
// Not blocked, just logged it
|
||||||
|
log.Error(errors.Wrap(err, "api controller: get project scanner"))
|
||||||
|
registration.Health = statusUnhealthy
|
||||||
|
} else {
|
||||||
|
registration.Health = statusHealthy
|
||||||
|
// Fill in some metadata
|
||||||
|
registration.Adapter = meta.Scanner.Name
|
||||||
|
registration.Vendor = meta.Scanner.Vendor
|
||||||
|
registration.Version = meta.Scanner.Version
|
||||||
|
}
|
||||||
|
|
||||||
return registration, err
|
return registration, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ type Registration struct {
|
|||||||
URL string `orm:"column(url);unique;size(512)" json:"url"`
|
URL string `orm:"column(url);unique;size(512)" json:"url"`
|
||||||
Disabled bool `orm:"column(disabled);default(true)" json:"disabled"`
|
Disabled bool `orm:"column(disabled);default(true)" json:"disabled"`
|
||||||
IsDefault bool `orm:"column(is_default);default(false)" json:"is_default"`
|
IsDefault bool `orm:"column(is_default);default(false)" json:"is_default"`
|
||||||
Health bool `orm:"-" json:"-"` // Reserved for future use
|
Health string `orm:"-" json:"health,omitempty"`
|
||||||
|
|
||||||
// Authentication settings
|
// Authentication settings
|
||||||
// "","Basic", "Bearer" and api key header "X-ScannerAdapter-API-Key" can be supported
|
// "","Basic", "Bearer" and api key header "X-ScannerAdapter-API-Key" can be supported
|
||||||
@ -53,6 +53,11 @@ type Registration struct {
|
|||||||
// Indicate if the registration is immutable which is not allowed to remove
|
// Indicate if the registration is immutable which is not allowed to remove
|
||||||
Immutable bool `orm:"column(immutable);default(false)" json:"-"`
|
Immutable bool `orm:"column(immutable);default(false)" json:"-"`
|
||||||
|
|
||||||
|
// Optional properties for describing the adapter
|
||||||
|
Adapter string `orm:"-" json:"adapter,omitempty"`
|
||||||
|
Vendor string `orm:"-" json:"vendor,omitempty"`
|
||||||
|
Version string `orm:"-" json:"version,omitempty"`
|
||||||
|
|
||||||
// Timestamps
|
// Timestamps
|
||||||
CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"create_time"`
|
CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"create_time"`
|
||||||
UpdateTime time.Time `orm:"column(update_time);auto_now;type(datetime)" json:"update_time"`
|
UpdateTime time.Time `orm:"column(update_time);auto_now;type(datetime)" json:"update_time"`
|
||||||
|
Loading…
Reference in New Issue
Block a user