mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-22 10:15:35 +01:00
support using internal registry addr to perform scan
- do changes to the sql schema - add `UseInternalAddr` and `Immutable` properties to scanner registration - support multiple authentication type - basic - bearer token Signed-off-by: Steven Zou <szou@vmware.com>
This commit is contained in:
parent
956d9db1d5
commit
cb59ba3bbc
@ -10,6 +10,8 @@ CREATE TABLE scanner_registration
|
||||
access_cred VARCHAR(512) NULL,
|
||||
disabled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
is_default BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
use_internal_addr BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
immutable BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
skip_cert_verify BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
|
@ -164,6 +164,12 @@ func (sa *ScannerAPI) Update() {
|
||||
return
|
||||
}
|
||||
|
||||
// Immutable registration is not allowed
|
||||
if r.Immutable {
|
||||
sa.SendForbiddenError(errors.Errorf("registration %s is not allowed to update as it is immutable: scanner API: update", r.Name))
|
||||
return
|
||||
}
|
||||
|
||||
// full dose updated
|
||||
rr := &scanner.Registration{}
|
||||
if err := sa.DecodeJSONReq(rr); err != nil {
|
||||
@ -207,17 +213,21 @@ func (sa *ScannerAPI) Update() {
|
||||
|
||||
// Delete the scanner
|
||||
func (sa *ScannerAPI) Delete() {
|
||||
uid := sa.GetStringFromPath(":uuid")
|
||||
|
||||
deleted, err := sa.c.DeleteRegistration(uid)
|
||||
if err != nil {
|
||||
sa.SendInternalServerError(errors.Wrap(err, "scanner API: delete"))
|
||||
r := sa.get()
|
||||
if r == nil {
|
||||
// meet error
|
||||
return
|
||||
}
|
||||
|
||||
if deleted == nil {
|
||||
// Not found
|
||||
sa.SendNotFoundError(errors.Errorf("scanner registration: %s", uid))
|
||||
// Immutable registration is not allowed
|
||||
if r.Immutable {
|
||||
sa.SendForbiddenError(errors.Errorf("registration %s is not allowed to delete as it is immutable: scanner API: update", r.Name))
|
||||
return
|
||||
}
|
||||
|
||||
deleted, err := sa.c.DeleteRegistration(r.UUID)
|
||||
if err != nil {
|
||||
sa.SendInternalServerError(errors.Wrap(err, "scanner API: delete"))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -227,6 +227,7 @@ func (suite *ScannerAPITestSuite) TestScannerAPIDelete() {
|
||||
URL: "https://a.b.c",
|
||||
}
|
||||
|
||||
suite.mockC.On("GetRegistration", "uuid").Return(r, nil)
|
||||
suite.mockC.On("DeleteRegistration", "uuid").Return(r, nil)
|
||||
|
||||
deleted := &scanner.Registration{}
|
||||
|
@ -19,11 +19,13 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
tk "github.com/docker/distribution/registry/auth/token"
|
||||
cj "github.com/goharbor/harbor/src/common/job"
|
||||
jm "github.com/goharbor/harbor/src/common/job/models"
|
||||
"github.com/goharbor/harbor/src/common/rbac"
|
||||
"github.com/goharbor/harbor/src/common/utils/log"
|
||||
"github.com/goharbor/harbor/src/core/config"
|
||||
"github.com/goharbor/harbor/src/core/service/token"
|
||||
"github.com/goharbor/harbor/src/jobservice/job"
|
||||
"github.com/goharbor/harbor/src/jobservice/logger"
|
||||
"github.com/goharbor/harbor/src/pkg/robot"
|
||||
@ -44,6 +46,9 @@ var DefaultController = NewController()
|
||||
const (
|
||||
configRegistryEndpoint = "registryEndpoint"
|
||||
configCoreInternalAddr = "coreInternalAddr"
|
||||
authorizationType = "harbor.scanner-adapter/registry-authorization-type"
|
||||
authorizationBearer = "Bearer"
|
||||
authorizationBasic = "Basic"
|
||||
)
|
||||
|
||||
// uuidGenerator is a func template which is for generating UUID.
|
||||
@ -190,7 +195,13 @@ func (bc *basicController) Scan(artifact *v1.Artifact) error {
|
||||
return errors.Wrap(err, "scan controller: scan")
|
||||
}
|
||||
|
||||
jobID, err := bc.launchScanJob(trackID, artifact, r, producesMimes)
|
||||
// Get authorization type
|
||||
auth := authorizationBasic
|
||||
if v, ok := meta.Properties[authorizationType]; ok {
|
||||
auth = v
|
||||
}
|
||||
|
||||
jobID, err := bc.launchScanJob(trackID, artifact, r, producesMimes, auth)
|
||||
if err != nil {
|
||||
// Update the status to the concrete error
|
||||
// Change status code to normal error code
|
||||
@ -352,8 +363,8 @@ func (bc *basicController) DeleteReports(digests ...string) error {
|
||||
return bc.manager.DeleteByDigests(digests...)
|
||||
}
|
||||
|
||||
// makeAuthorization creates authorization from a robot account based on the arguments for scanning.
|
||||
func (bc *basicController) makeAuthorization(pid int64, repository string, ttl int64) (string, int64, error) {
|
||||
// makeBasicAuthorization creates authorization from a robot account based on the arguments for scanning.
|
||||
func (bc *basicController) makeBasicAuthorization(pid int64, repository string, ttl int64) (string, int64, error) {
|
||||
// Use uuid as name to avoid duplicated entries.
|
||||
UUID, err := bc.uuid()
|
||||
if err != nil {
|
||||
@ -389,14 +400,31 @@ func (bc *basicController) makeAuthorization(pid int64, repository string, ttl i
|
||||
}
|
||||
|
||||
// launchScanJob launches a job to run scan
|
||||
func (bc *basicController) launchScanJob(trackID string, artifact *v1.Artifact, registration *scanner.Registration, mimes []string) (jobID string, err error) {
|
||||
externalURL, err := bc.config(configRegistryEndpoint)
|
||||
func (bc *basicController) launchScanJob(trackID string, artifact *v1.Artifact, registration *scanner.Registration, mimes []string, auth string) (jobID string, err error) {
|
||||
var ck string
|
||||
if registration.UseInternalAddr {
|
||||
ck = configCoreInternalAddr
|
||||
} else {
|
||||
ck = configRegistryEndpoint
|
||||
}
|
||||
|
||||
registryAddr, err := bc.config(ck)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "scan controller: launch scan job")
|
||||
}
|
||||
|
||||
// Make authorization from a robot account with 30 minutes
|
||||
authorization, rID, err := bc.makeAuthorization(artifact.NamespaceID, artifact.Repository, 1800)
|
||||
var (
|
||||
authorization string
|
||||
rID int64 = -1
|
||||
)
|
||||
|
||||
if auth == authorizationBearer {
|
||||
authorization, err = makeBearerAuthorization(artifact.Repository, fmt.Sprintf("%s:%s", registration.Name, registration.UUID))
|
||||
} else {
|
||||
// Make authorization from a robot account with 30 minutes
|
||||
authorization, rID, err = bc.makeBasicAuthorization(artifact.NamespaceID, artifact.Repository, 1800)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "scan controller: launch scan job")
|
||||
}
|
||||
@ -404,7 +432,7 @@ func (bc *basicController) launchScanJob(trackID string, artifact *v1.Artifact,
|
||||
// Set job parameters
|
||||
scanReq := &v1.ScanRequest{
|
||||
Registry: &v1.Registry{
|
||||
URL: externalURL,
|
||||
URL: registryAddr,
|
||||
Authorization: authorization,
|
||||
},
|
||||
Artifact: artifact,
|
||||
@ -424,7 +452,9 @@ func (bc *basicController) launchScanJob(trackID string, artifact *v1.Artifact,
|
||||
params[sca.JobParamRegistration] = rJSON
|
||||
params[sca.JobParameterRequest] = sJSON
|
||||
params[sca.JobParameterMimes] = mimes
|
||||
params[sca.JobParameterRobotID] = rID
|
||||
if rID > 0 {
|
||||
params[sca.JobParameterRobotID] = rID
|
||||
}
|
||||
|
||||
// Launch job
|
||||
callbackURL, err := bc.config(configCoreInternalAddr)
|
||||
@ -444,3 +474,21 @@ func (bc *basicController) launchScanJob(trackID string, artifact *v1.Artifact,
|
||||
|
||||
return bc.jc().SubmitJob(j)
|
||||
}
|
||||
|
||||
// makeBearerAuthorization make a authorization with bearer token
|
||||
func makeBearerAuthorization(repository string, username string) (string, error) {
|
||||
access := []*tk.ResourceActions{
|
||||
{
|
||||
Type: "repository",
|
||||
Name: repository,
|
||||
Actions: []string{"pull"},
|
||||
},
|
||||
}
|
||||
|
||||
accessToken, err := token.MakeToken(username, token.Registry, access)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "make bearer authorization")
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Bearer %s", accessToken.Token), nil
|
||||
}
|
||||
|
@ -118,7 +118,11 @@ func (bc *basicController) UpdateRegistration(registration *scanner.Registration
|
||||
// SetDefaultRegistration ...
|
||||
func (bc *basicController) DeleteRegistration(registrationUUID string) (*scanner.Registration, error) {
|
||||
registration, err := bc.manager.Get(registrationUUID)
|
||||
if registration == nil && err == nil {
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "api controller: delete registration")
|
||||
}
|
||||
|
||||
if registration == nil {
|
||||
// Not found
|
||||
return nil, nil
|
||||
}
|
||||
|
@ -47,6 +47,12 @@ type Registration struct {
|
||||
// Http connection settings
|
||||
SkipCertVerify bool `orm:"column(skip_cert_verify);default(false)" json:"skip_certVerify"`
|
||||
|
||||
// Indicate whether use internal registry addr for the scanner to pull content
|
||||
UseInternalAddr bool `orm:"column(use_internal_addr);default(false)" json:"use_internal_addr"`
|
||||
|
||||
// Indicate if the registration is immutable which is not allowed to remove
|
||||
Immutable bool `orm:"column(immutable);default(false)" json:"-"`
|
||||
|
||||
// Timestamps
|
||||
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"`
|
||||
|
Loading…
Reference in New Issue
Block a user