mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-21 08:07:59 +01:00
Merge pull request #9571 from steven-zou/fix/support_internal_addr_scanner
support using internal registry addr to perform scan
This commit is contained in:
commit
868851cc51
@ -10,6 +10,8 @@ CREATE TABLE scanner_registration
|
|||||||
access_cred VARCHAR(512) NULL,
|
access_cred VARCHAR(512) NULL,
|
||||||
disabled BOOLEAN NOT NULL DEFAULT FALSE,
|
disabled BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
is_default 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,
|
skip_cert_verify BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
@ -164,6 +164,12 @@ func (sa *ScannerAPI) Update() {
|
|||||||
return
|
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
|
// full dose updated
|
||||||
rr := &scanner.Registration{}
|
rr := &scanner.Registration{}
|
||||||
if err := sa.DecodeJSONReq(rr); err != nil {
|
if err := sa.DecodeJSONReq(rr); err != nil {
|
||||||
@ -207,17 +213,21 @@ func (sa *ScannerAPI) Update() {
|
|||||||
|
|
||||||
// Delete the scanner
|
// Delete the scanner
|
||||||
func (sa *ScannerAPI) Delete() {
|
func (sa *ScannerAPI) Delete() {
|
||||||
uid := sa.GetStringFromPath(":uuid")
|
r := sa.get()
|
||||||
|
if r == nil {
|
||||||
deleted, err := sa.c.DeleteRegistration(uid)
|
// meet error
|
||||||
if err != nil {
|
|
||||||
sa.SendInternalServerError(errors.Wrap(err, "scanner API: delete"))
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if deleted == nil {
|
// Immutable registration is not allowed
|
||||||
// Not found
|
if r.Immutable {
|
||||||
sa.SendNotFoundError(errors.Errorf("scanner registration: %s", uid))
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,6 +227,7 @@ func (suite *ScannerAPITestSuite) TestScannerAPIDelete() {
|
|||||||
URL: "https://a.b.c",
|
URL: "https://a.b.c",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suite.mockC.On("GetRegistration", "uuid").Return(r, nil)
|
||||||
suite.mockC.On("DeleteRegistration", "uuid").Return(r, nil)
|
suite.mockC.On("DeleteRegistration", "uuid").Return(r, nil)
|
||||||
|
|
||||||
deleted := &scanner.Registration{}
|
deleted := &scanner.Registration{}
|
||||||
|
@ -19,11 +19,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
tk "github.com/docker/distribution/registry/auth/token"
|
||||||
cj "github.com/goharbor/harbor/src/common/job"
|
cj "github.com/goharbor/harbor/src/common/job"
|
||||||
jm "github.com/goharbor/harbor/src/common/job/models"
|
jm "github.com/goharbor/harbor/src/common/job/models"
|
||||||
"github.com/goharbor/harbor/src/common/rbac"
|
"github.com/goharbor/harbor/src/common/rbac"
|
||||||
"github.com/goharbor/harbor/src/common/utils/log"
|
"github.com/goharbor/harbor/src/common/utils/log"
|
||||||
"github.com/goharbor/harbor/src/core/config"
|
"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/job"
|
||||||
"github.com/goharbor/harbor/src/jobservice/logger"
|
"github.com/goharbor/harbor/src/jobservice/logger"
|
||||||
"github.com/goharbor/harbor/src/pkg/robot"
|
"github.com/goharbor/harbor/src/pkg/robot"
|
||||||
@ -44,6 +46,9 @@ var DefaultController = NewController()
|
|||||||
const (
|
const (
|
||||||
configRegistryEndpoint = "registryEndpoint"
|
configRegistryEndpoint = "registryEndpoint"
|
||||||
configCoreInternalAddr = "coreInternalAddr"
|
configCoreInternalAddr = "coreInternalAddr"
|
||||||
|
authorizationType = "harbor.scanner-adapter/registry-authorization-type"
|
||||||
|
authorizationBearer = "Bearer"
|
||||||
|
authorizationBasic = "Basic"
|
||||||
)
|
)
|
||||||
|
|
||||||
// uuidGenerator is a func template which is for generating UUID.
|
// 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")
|
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 {
|
if err != nil {
|
||||||
// Update the status to the concrete error
|
// Update the status to the concrete error
|
||||||
// Change status code to normal error code
|
// Change status code to normal error code
|
||||||
@ -352,8 +363,8 @@ func (bc *basicController) DeleteReports(digests ...string) error {
|
|||||||
return bc.manager.DeleteByDigests(digests...)
|
return bc.manager.DeleteByDigests(digests...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeAuthorization creates authorization from a robot account based on the arguments for scanning.
|
// makeBasicAuthorization 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) {
|
func (bc *basicController) makeBasicAuthorization(pid int64, repository string, ttl int64) (string, int64, error) {
|
||||||
// Use uuid as name to avoid duplicated entries.
|
// Use uuid as name to avoid duplicated entries.
|
||||||
UUID, err := bc.uuid()
|
UUID, err := bc.uuid()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -389,14 +400,31 @@ func (bc *basicController) makeAuthorization(pid int64, repository string, ttl i
|
|||||||
}
|
}
|
||||||
|
|
||||||
// launchScanJob launches a job to run scan
|
// 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) {
|
func (bc *basicController) launchScanJob(trackID string, artifact *v1.Artifact, registration *scanner.Registration, mimes []string, auth string) (jobID string, err error) {
|
||||||
externalURL, err := bc.config(configRegistryEndpoint)
|
var ck string
|
||||||
|
if registration.UseInternalAddr {
|
||||||
|
ck = configCoreInternalAddr
|
||||||
|
} else {
|
||||||
|
ck = configRegistryEndpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
registryAddr, err := bc.config(ck)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "scan controller: launch scan job")
|
return "", errors.Wrap(err, "scan controller: launch scan job")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make authorization from a robot account with 30 minutes
|
var (
|
||||||
authorization, rID, err := bc.makeAuthorization(artifact.NamespaceID, artifact.Repository, 1800)
|
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 {
|
if err != nil {
|
||||||
return "", errors.Wrap(err, "scan controller: launch scan job")
|
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
|
// Set job parameters
|
||||||
scanReq := &v1.ScanRequest{
|
scanReq := &v1.ScanRequest{
|
||||||
Registry: &v1.Registry{
|
Registry: &v1.Registry{
|
||||||
URL: externalURL,
|
URL: registryAddr,
|
||||||
Authorization: authorization,
|
Authorization: authorization,
|
||||||
},
|
},
|
||||||
Artifact: artifact,
|
Artifact: artifact,
|
||||||
@ -424,7 +452,9 @@ func (bc *basicController) launchScanJob(trackID string, artifact *v1.Artifact,
|
|||||||
params[sca.JobParamRegistration] = rJSON
|
params[sca.JobParamRegistration] = rJSON
|
||||||
params[sca.JobParameterRequest] = sJSON
|
params[sca.JobParameterRequest] = sJSON
|
||||||
params[sca.JobParameterMimes] = mimes
|
params[sca.JobParameterMimes] = mimes
|
||||||
params[sca.JobParameterRobotID] = rID
|
if rID > 0 {
|
||||||
|
params[sca.JobParameterRobotID] = rID
|
||||||
|
}
|
||||||
|
|
||||||
// Launch job
|
// Launch job
|
||||||
callbackURL, err := bc.config(configCoreInternalAddr)
|
callbackURL, err := bc.config(configCoreInternalAddr)
|
||||||
@ -444,3 +474,21 @@ func (bc *basicController) launchScanJob(trackID string, artifact *v1.Artifact,
|
|||||||
|
|
||||||
return bc.jc().SubmitJob(j)
|
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 ...
|
// SetDefaultRegistration ...
|
||||||
func (bc *basicController) DeleteRegistration(registrationUUID string) (*scanner.Registration, error) {
|
func (bc *basicController) DeleteRegistration(registrationUUID string) (*scanner.Registration, error) {
|
||||||
registration, err := bc.manager.Get(registrationUUID)
|
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
|
// Not found
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,12 @@ type Registration struct {
|
|||||||
// Http connection settings
|
// Http connection settings
|
||||||
SkipCertVerify bool `orm:"column(skip_cert_verify);default(false)" json:"skip_certVerify"`
|
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
|
// 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