Skip to content

Commit

Permalink
Merge branch 'main' into replication-cron-check
Browse files Browse the repository at this point in the history
  • Loading branch information
Shengwen YU authored Jul 20, 2023
2 parents 4d08048 + 5e4163b commit 46e3216
Show file tree
Hide file tree
Showing 106 changed files with 3,344 additions and 241 deletions.
106 changes: 104 additions & 2 deletions api/v2.0/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6063,13 +6063,13 @@ paths:
- $ref: '#/parameters/requestId'
- name: with_dangerous_cve
in: query
description: Specify whether the dangerous CVE is include in the security summary
description: Specify whether the dangerous CVEs are included inside summary information
type: boolean
required: false
default: false
- name: with_dangerous_artifact
in: query
description: Specify whether the dangerous artifacts is include in the security summary
description: Specify whether the dangerous Artifact are included inside summary information
type: boolean
required: false
default: false
Expand All @@ -6086,6 +6086,61 @@ paths:
$ref: '#/responses/404'
'500':
$ref: '#/responses/500'

/security/vul:
get:
summary: Get the vulnerability list.
description: |
Get the vulnerability list. use q to pass the query condition,
supported conditions:
cve_id(exact match)
cvss_score_v3(range condition)
severity(exact match)
repository_name(exact match)
project_id(exact match)
package(exact match)
and tag(exact match)
tags:
- securityhub
operationId: ListVulnerabilities
parameters:
- $ref: '#/parameters/requestId'
- $ref: '#/parameters/query'
- $ref: '#/parameters/page'
- $ref: '#/parameters/pageSize'
- name: tune_count
in: query
description: Enable to ignore X-Total-Count when the total count > 1000, if the total count is less than 1000, the real total count is returned, else -1.
type: boolean
required: false
default: false
- name: with_tag
in: query
description: Specify whether the tag information is included inside vulnerability information
type: boolean
required: false
default: false
responses:
'200':
description: The vulnerability list.
schema:
type: array
items:
$ref: '#/definitions/VulnerabilityItem'
headers:
X-Total-Count:
description: The total count of vulnerabilities
type: integer
Link:
description: Link refers to the previous page and next page
type: string
'400':
$ref: '#/responses/400'
'401':
$ref: '#/responses/401'
'500':
$ref: '#/responses/500'

parameters:
query:
name: q
Expand Down Expand Up @@ -9760,3 +9815,50 @@ definitions:
type: integer
x-omitempty: false
description: the count of medium vulnerabilities

VulnerabilityItem:
type: object
description: the vulnerability item info
properties:
project_id:
type: integer
format: int64
description: the project ID of the artifact
repository_name:
type: string
description: the repository name of the artifact
digest:
type: string
description: the digest of the artifact
tags:
type: array
items:
type: string
description: the tags of the artifact
cve_id:
type: string
description: the CVE id of the vulnerability.
severity:
type: string
description: the severity of the vulnerability
cvss_v3_score:
type: number
format: float
description: the nvd cvss v3 score of the vulnerability
package:
type: string
description: the package of the vulnerability
version:
type: string
description: the version of the package
fixed_version:
type: string
description: the fixed version of the package
desc:
type: string
description: The description of the vulnerability
links:
type: array
items:
type: string
description: Links of the vulnerability
15 changes: 15 additions & 0 deletions make/migrations/postgresql/0120_2.9.0_schema.up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ UPDATE vulnerability_record
SET cvss_score_v3 = (vendor_attributes->'CVSS'->'nvd'->>'V3Score')::double precision
WHERE jsonb_path_exists(vendor_attributes::jsonb, '$.CVSS.nvd.V3Score');

CREATE INDEX IF NOT EXISTS idx_vulnerability_record_cvss_score_v3 ON vulnerability_record (cvss_score_v3);
CREATE INDEX IF NOT EXISTS idx_vulnerability_registration_uuid ON vulnerability_record (registration_uuid);
CREATE INDEX IF NOT EXISTS idx_vulnerability_record_cve_id ON vulnerability_record (cve_id);
CREATE INDEX IF NOT EXISTS idx_vulnerability_record_severity ON vulnerability_record (severity);
CREATE INDEX IF NOT EXISTS idx_vulnerability_record_package ON vulnerability_record (package);

/* add summary information in scan_report */
ALTER TABLE scan_report ADD COLUMN IF NOT EXISTS critical_cnt BIGINT;
ALTER TABLE scan_report ADD COLUMN IF NOT EXISTS high_cnt BIGINT;
Expand Down Expand Up @@ -74,3 +80,12 @@ $$
END LOOP;
END
$$;

/* Refactor the structure of replication schedule callback_func_param, convert the raw id to json object for extending */
/* callback_func_param
Old: 100
New: {"policy_id": 100}
*/
UPDATE schedule SET callback_func_param = json_build_object('policy_id', callback_func_param::int)::text
WHERE vendor_type='REPLICATION'
AND callback_func_param NOT LIKE '%policy_id%';
1 change: 1 addition & 0 deletions src/common/rbac/system/policies.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,5 +86,6 @@ var (
{Resource: rbac.ResourceJobServiceMonitor, Action: rbac.ActionStop},

{Resource: rbac.ResourceSecurityHub, Action: rbac.ActionRead},
{Resource: rbac.ResourceSecurityHub, Action: rbac.ActionList},
}
)
5 changes: 5 additions & 0 deletions src/controller/event/handler/internal/artifact.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (

"github.com/goharbor/harbor/src/controller/artifact"
"github.com/goharbor/harbor/src/controller/event"
"github.com/goharbor/harbor/src/controller/event/operator"
"github.com/goharbor/harbor/src/controller/repository"
"github.com/goharbor/harbor/src/controller/tag"
"github.com/goharbor/harbor/src/jobservice/job"
Expand Down Expand Up @@ -246,6 +247,10 @@ func (a *Handler) asyncFlushPullCount(ctx context.Context) {

func (a *Handler) onPush(ctx context.Context, event *event.ArtifactEvent) error {
go func() {
if event.Operator != "" {
ctx = context.WithValue(ctx, operator.ContextKey{}, event.Operator)
}

if err := autoScan(ctx, &artifact.Artifact{Artifact: *event.Artifact}, event.Tags...); err != nil {
log.Errorf("scan artifact %s@%s failed, error: %v", event.Artifact.RepositoryName, event.Artifact.Digest, err)
}
Expand Down
1 change: 1 addition & 0 deletions src/controller/event/handler/replication/event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ const (
type Event struct {
Type string
Resource *model.Resource
Operator string
}
5 changes: 5 additions & 0 deletions src/controller/event/handler/replication/event/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"errors"
"fmt"

"github.com/goharbor/harbor/src/controller/event/operator"
"github.com/goharbor/harbor/src/controller/replication"
repctlmodel "github.com/goharbor/harbor/src/controller/replication/model"
"github.com/goharbor/harbor/src/lib/log"
Expand Down Expand Up @@ -51,6 +52,10 @@ func Handle(ctx context.Context, event *Event) error {
return nil
}

if event.Operator != "" {
ctx = context.WithValue(ctx, operator.ContextKey{}, event.Operator)
}

for _, policy := range policies {
id, err := replication.Ctl.Start(ctx, policy, event.Resource, task.ExecutionTriggerEvent)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions src/controller/event/handler/replication/replication.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ func (r *Handler) handlePushArtifact(ctx context.Context, event *event.PushArtif
}},
},
},
Operator: event.Operator,
}
return repevent.Handle(ctx, e)
}
Expand Down Expand Up @@ -140,6 +141,7 @@ func (r *Handler) handleDeleteArtifact(ctx context.Context, event *event.DeleteA
},
Deleted: true,
},
Operator: event.Operator,
}
return repevent.Handle(ctx, e)
}
Expand Down Expand Up @@ -180,6 +182,7 @@ func (r *Handler) handleCreateTag(ctx context.Context, event *event.CreateTagEve
}},
},
},
Operator: event.Operator,
}
return repevent.Handle(ctx, e)
}
Expand Down Expand Up @@ -212,6 +215,7 @@ func (r *Handler) handleDeleteTag(ctx context.Context, event *event.DeleteTagEve
Deleted: true,
IsDeleteTag: true,
},
Operator: event.Operator,
}
return repevent.Handle(ctx, e)
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ func constructReplicationPayload(ctx context.Context, event *event.ReplicationEv
payload := &model.Payload{
Type: event.EventType,
OccurAt: event.OccurAt.Unix(),
Operator: string(execution.Trigger),
Operator: execution.Operator,
EventData: &model.EventData{
Replication: &ctlModel.Replication{
HarborHostname: hostname,
Expand Down
2 changes: 1 addition & 1 deletion src/controller/event/handler/webhook/artifact/retention.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func (r *RetentionHandler) constructRetentionPayload(ctx context.Context, event
payload := &model.Payload{
Type: event.EventType,
OccurAt: event.OccurAt.Unix(),
Operator: execution.Trigger,
Operator: execution.Operator,
EventData: &model.EventData{
Retention: &evtModel.Retention{
Total: event.Total,
Expand Down
1 change: 1 addition & 0 deletions src/controller/event/handler/webhook/quota/quota.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ func constructQuotaPayload(event *event.QuotaEvent) (*notifyModel.Payload, error
},
Custom: quotaCustom,
},
Operator: event.Operator,
}

if event.Resource != nil {
Expand Down
6 changes: 4 additions & 2 deletions src/controller/event/metadata/quota.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ type QuotaMetaData struct {
// used to define the event topic
Level int
// the msg contains the limitation and current usage of quota
Msg string
OccurAt time.Time
Msg string
OccurAt time.Time
Operator string
}

// Resolve quota exceed into common image event
Expand All @@ -54,6 +55,7 @@ func (q *QuotaMetaData) Resolve(evt *event.Event) error {
OccurAt: q.OccurAt,
RepoName: q.RepoName,
Msg: q.Msg,
Operator: q.Operator,
}
if q.Tag != "" || q.Digest != "" {
data.Resource = &event2.ImgResource{
Expand Down
7 changes: 2 additions & 5 deletions src/controller/event/metadata/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,11 @@ import (
v1 "github.com/goharbor/harbor/src/pkg/scan/rest/v1"
)

const (
autoTriggeredOperator = "auto"
)

// ScanImageMetaData defines meta data of image scanning event
type ScanImageMetaData struct {
Artifact *v1.Artifact
Status string
Operator string
}

// Resolve image scanning metadata into common chart event
Expand All @@ -57,7 +54,7 @@ func (si *ScanImageMetaData) Resolve(evt *event.Event) error {
EventType: eventType,
Artifact: si.Artifact,
OccurAt: time.Now(),
Operator: autoTriggeredOperator,
Operator: si.Operator,
}

evt.Topic = topic
Expand Down
17 changes: 14 additions & 3 deletions src/controller/event/operator/operator.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,23 @@ import (
"github.com/goharbor/harbor/src/common/security"
)

// ContextKey is the key for storing operator in the context.
type ContextKey struct{}

// FromContext return the event operator from context
func FromContext(ctx context.Context) string {
var operator string
sc, ok := security.FromContext(ctx)
if !ok {
return ""
if ok {
operator = sc.GetUsername()
}
// retrieve from context if not found in security context
if operator == "" {
op, ok := ctx.Value(ContextKey{}).(string)
if ok {
operator = op
}
}

return sc.GetUsername()
return operator
}
47 changes: 47 additions & 0 deletions src/controller/event/operator/operator_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright Project Harbor Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package operator

import (
"context"
"testing"

"github.com/goharbor/harbor/src/common/security"
testsec "github.com/goharbor/harbor/src/testing/common/security"

"github.com/stretchr/testify/assert"
)

func TestFromContext(t *testing.T) {
{
// no security context and operator context should return ""
op := FromContext(context.Background())
assert.Empty(t, op)
}
{
// return operator from security context
secCtx := &testsec.Context{}
secCtx.On("GetUsername").Return("security-context-user")
ctx := security.NewContext(context.Background(), secCtx)
op := FromContext(ctx)
assert.Equal(t, "security-context-user", op)
}
{
// return operator from operator context
ctx := context.WithValue(context.Background(), ContextKey{}, "operator-context-user")
op := FromContext(ctx)
assert.Equal(t, "operator-context-user", op)
}
}
1 change: 1 addition & 0 deletions src/controller/event/topic.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ type QuotaEvent struct {
OccurAt time.Time
RepoName string
Msg string
Operator string
}

func (q *QuotaEvent) String() string {
Expand Down
Loading

0 comments on commit 46e3216

Please sign in to comment.