mirror of
https://github.com/goharbor/harbor.git
synced 2024-12-23 00:57:44 +01:00
Remove clair notifier
The way Harbor handles notification is problematic. It currently triggers rescan, which will cause problem when there are lot of images in the registry. Such as #7316 This commit removes the notifier and we need to revisit the notification to figure out how to map the notification to a particular image if need the notification mechanism in future. Signed-off-by: Daniel Jiang <jiangd@vmware.com>
This commit is contained in:
parent
12fb643f0a
commit
eec4fc2798
@ -17,9 +17,3 @@ clair:
|
||||
timeout: 300s
|
||||
updater:
|
||||
interval: {{clair_updaters_interval}}h
|
||||
|
||||
notifier:
|
||||
attempts: 3
|
||||
renotifyinterval: 2h
|
||||
http:
|
||||
endpoint: http://core:8080/service/notifications/clair
|
||||
|
@ -15,10 +15,7 @@
|
||||
package clair
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/goharbor/harbor/src/common/dao"
|
||||
"github.com/goharbor/harbor/src/common/models"
|
||||
"github.com/goharbor/harbor/src/common/utils/log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -41,26 +38,6 @@ func ParseClairSev(clairSev string) models.Severity {
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateScanOverview qeuries the vulnerability based on the layerName and update the record in img_scan_overview table based on digest.
|
||||
func UpdateScanOverview(digest, layerName string, clairEndpoint string, l ...*log.Logger) error {
|
||||
var logger *log.Logger
|
||||
if len(l) > 1 {
|
||||
return fmt.Errorf("More than one logger specified")
|
||||
} else if len(l) == 1 {
|
||||
logger = l[0]
|
||||
} else {
|
||||
logger = log.DefaultLogger()
|
||||
}
|
||||
client := NewClient(clairEndpoint, logger)
|
||||
res, err := client.GetResult(layerName)
|
||||
if err != nil {
|
||||
logger.Errorf("Failed to get result from Clair, error: %v", err)
|
||||
return err
|
||||
}
|
||||
compOverview, sev := transformVuln(res)
|
||||
return dao.UpdateImgScanOverview(digest, layerName, sev, compOverview)
|
||||
}
|
||||
|
||||
func transformVuln(clairVuln *models.ClairLayerEnvelope) (*models.ComponentsOverview, models.Severity) {
|
||||
vulnMap := make(map[models.Severity]int)
|
||||
features := clairVuln.Layer.Features
|
||||
|
@ -20,7 +20,6 @@ import (
|
||||
"github.com/goharbor/harbor/src/core/config"
|
||||
"github.com/goharbor/harbor/src/core/controllers"
|
||||
"github.com/goharbor/harbor/src/core/service/notifications/admin"
|
||||
"github.com/goharbor/harbor/src/core/service/notifications/clair"
|
||||
"github.com/goharbor/harbor/src/core/service/notifications/jobs"
|
||||
"github.com/goharbor/harbor/src/core/service/notifications/registry"
|
||||
"github.com/goharbor/harbor/src/core/service/notifications/scheduler"
|
||||
@ -131,7 +130,6 @@ func initRouters() {
|
||||
|
||||
// external service that hosted on harbor process:
|
||||
beego.Router("/service/notifications", ®istry.NotificationHandler{})
|
||||
beego.Router("/service/notifications/clair", &clair.Handler{}, "post:Handle")
|
||||
beego.Router("/service/notifications/jobs/scan/:id([0-9]+)", &jobs.Handler{}, "post:HandleScan")
|
||||
beego.Router("/service/notifications/jobs/adminjob/:id([0-9]+)", &admin.Handler{}, "post:HandleAdminJob")
|
||||
beego.Router("/service/notifications/jobs/replication/:id([0-9]+)", &jobs.Handler{}, "post:HandleReplicationScheduleJob")
|
||||
|
@ -1,107 +0,0 @@
|
||||
// Copyright 2018 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 clair
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/goharbor/harbor/src/common/dao"
|
||||
"github.com/goharbor/harbor/src/common/models"
|
||||
"github.com/goharbor/harbor/src/common/utils"
|
||||
"github.com/goharbor/harbor/src/common/utils/clair"
|
||||
"github.com/goharbor/harbor/src/common/utils/log"
|
||||
"github.com/goharbor/harbor/src/core/api"
|
||||
"github.com/goharbor/harbor/src/core/config"
|
||||
)
|
||||
|
||||
const (
|
||||
rescanInterval = 15 * time.Minute
|
||||
)
|
||||
|
||||
var (
|
||||
clairClient *clair.Client
|
||||
)
|
||||
|
||||
// Handler handles reqeust on /service/notifications/clair/, which listens to clair's notifications.
|
||||
// When there's unexpected error it will silently fail without removing the notification such that it will be triggered again.
|
||||
type Handler struct {
|
||||
api.BaseController
|
||||
}
|
||||
|
||||
// Handle ...
|
||||
func (h *Handler) Handle() {
|
||||
if clairClient == nil {
|
||||
clairClient = clair.NewClient(config.ClairEndpoint(), nil)
|
||||
}
|
||||
var ne models.ClairNotificationEnvelope
|
||||
if err := json.Unmarshal(h.Ctx.Input.CopyBody(1<<32), &ne); err != nil {
|
||||
log.Errorf("Failed to decode the request: %v", err)
|
||||
return
|
||||
}
|
||||
log.Debugf("Received notification from Clair, name: %s", ne.Notification.Name)
|
||||
notification, err := clairClient.GetNotification(ne.Notification.Name)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to get notification details from Clair, name: %s, err: %v", ne.Notification.Name, err)
|
||||
return
|
||||
}
|
||||
ns := make(map[string]bool)
|
||||
if old := notification.Old; old != nil {
|
||||
if vuln := old.Vulnerability; vuln != nil {
|
||||
log.Debugf("old vulnerability namespace: %s", vuln.NamespaceName)
|
||||
ns[vuln.NamespaceName] = true
|
||||
}
|
||||
}
|
||||
if newNotification := notification.New; newNotification != nil {
|
||||
if vuln := newNotification.Vulnerability; vuln != nil {
|
||||
log.Debugf("new vulnerability namespace: %s", vuln.NamespaceName)
|
||||
ns[vuln.NamespaceName] = true
|
||||
}
|
||||
}
|
||||
for k, v := range ns {
|
||||
if v {
|
||||
if err := dao.SetClairVulnTimestamp(k, time.Now()); err == nil {
|
||||
log.Debugf("Updated the timestamp for namespaces: %s", k)
|
||||
} else {
|
||||
log.Warningf("Failed to update the timestamp for namespaces: %s, error: %v", k, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if utils.ScanOverviewMarker().Check() {
|
||||
go func() {
|
||||
<-time.After(rescanInterval)
|
||||
l, err := dao.ListImgScanOverviews()
|
||||
if err != nil {
|
||||
log.Errorf("Failed to list scan overview records, error: %v", err)
|
||||
return
|
||||
}
|
||||
for _, e := range l {
|
||||
if err := clair.UpdateScanOverview(e.Digest, e.DetailsKey, config.ClairEndpoint()); err != nil {
|
||||
log.Errorf("Failed to refresh scan overview for image: %s", e.Digest)
|
||||
} else {
|
||||
log.Debugf("Refreshed scan overview for record with digest: %s", e.Digest)
|
||||
}
|
||||
}
|
||||
}()
|
||||
utils.ScanOverviewMarker().Mark()
|
||||
} else {
|
||||
log.Debugf("There is a rescan scheduled at %v already, skip.", utils.ScanOverviewMarker().Next())
|
||||
}
|
||||
if err := clairClient.DeleteNotification(ne.Notification.Name); err != nil {
|
||||
log.Warningf("Failed to remove notification from Clair, name: %s", ne.Notification.Name)
|
||||
} else {
|
||||
log.Debugf("Removed notification from Clair, name: %s", ne.Notification.Name)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user