diff --git a/api/v2.0/swagger.yaml b/api/v2.0/swagger.yaml index 54e808400..3da7a7251 100644 --- a/api/v2.0/swagger.yaml +++ b/api/v2.0/swagger.yaml @@ -299,6 +299,29 @@ paths: $ref: '#/responses/404' '500': $ref: '#/responses/500' + /projects/{project_name}/repositories/{repository_name}/artifacts/{reference}/scan: + post: + summary: Scan the artifact + description: Scan the specified artifact + tags: + - artifact + operationId: scanArtifact + parameters: + - $ref: '#/parameters/requestId' + - $ref: '#/parameters/projectName' + - $ref: '#/parameters/repositoryName' + - $ref: '#/parameters/reference' + responses: + '202': + $ref: '#/responses/202' + '401': + $ref: '#/responses/401' + '403': + $ref: '#/responses/403' + '404': + $ref: '#/responses/404' + '500': + $ref: '#/responses/500' /projects/{project_name}/repositories/{repository_name}/artifacts/{reference}/tags: post: summary: Create tag @@ -512,6 +535,12 @@ responses: X-Request-Id: description: The ID of the corresponding request for the response type: string + '202': + description: Accepted + headers: + X-Request-Id: + description: The ID of the corresponding request for the response + type: string '400': description: Bad request headers: diff --git a/src/server/v2.0/handler/artifact.go b/src/server/v2.0/handler/artifact.go index c3b212f63..270e905c2 100644 --- a/src/server/v2.0/handler/artifact.go +++ b/src/server/v2.0/handler/artifact.go @@ -27,11 +27,13 @@ import ( "github.com/goharbor/harbor/src/api/artifact" "github.com/goharbor/harbor/src/api/artifact/abstractor/resolver" "github.com/goharbor/harbor/src/api/repository" + "github.com/goharbor/harbor/src/api/scan" "github.com/goharbor/harbor/src/common/rbac" "github.com/goharbor/harbor/src/common/utils" ierror "github.com/goharbor/harbor/src/internal/error" "github.com/goharbor/harbor/src/pkg/project" "github.com/goharbor/harbor/src/pkg/q" + v1 "github.com/goharbor/harbor/src/pkg/scan/rest/v1" "github.com/goharbor/harbor/src/server/v2.0/handler/assembler" "github.com/goharbor/harbor/src/server/v2.0/handler/model" operation "github.com/goharbor/harbor/src/server/v2.0/restapi/operations/artifact" @@ -47,6 +49,7 @@ func newArtifactAPI() *artifactAPI { artCtl: artifact.Ctl, proMgr: project.Mgr, repoCtl: repository.Ctl, + scanCtl: scan.DefaultController, } } @@ -55,6 +58,7 @@ type artifactAPI struct { artCtl artifact.Controller proMgr project.Manager repoCtl repository.Controller + scanCtl scan.Controller } func (a *artifactAPI) ListArtifacts(ctx context.Context, params operation.ListArtifactsParams) middleware.Responder { @@ -176,6 +180,30 @@ func (a *artifactAPI) CopyArtifact(ctx context.Context, params operation.CopyArt return operation.NewCopyArtifactCreated() } +func (a *artifactAPI) ScanArtifact(ctx context.Context, params operation.ScanArtifactParams) middleware.Responder { + if err := a.RequireProjectAccess(ctx, params.ProjectName, rbac.ActionCreate, rbac.ResourceScan); err != nil { + return a.SendError(ctx, err) + } + + repository := fmt.Sprintf("%s/%s", params.ProjectName, params.RepositoryName) + artifact, err := a.artCtl.GetByReference(ctx, repository, params.Reference, nil) + if err != nil { + return a.SendError(ctx, err) + } + + art := &v1.Artifact{ + NamespaceID: artifact.ProjectID, + Repository: repository, + Digest: artifact.Digest, + MimeType: artifact.ManifestMediaType, + } + if err := a.scanCtl.Scan(art); err != nil { + return a.SendError(ctx, err) + } + + return operation.NewScanArtifactAccepted() +} + // parse "repository:tag" or "repository@digest" into repository and reference parts func parse(s string) (string, string, error) { matches := reference.ReferenceRegexp.FindStringSubmatch(s)