Skip to content

Commit

Permalink
Add user login event to audit log
Browse files Browse the repository at this point in the history
  Add common event handler
  Register login event
  Update previous audit log event redirect to auditlogext table

Signed-off-by: stonezdj <[email protected]>
  • Loading branch information
stonezdj committed Jan 15, 2025
1 parent 60798a4 commit 9cc5065
Show file tree
Hide file tree
Showing 9 changed files with 348 additions and 87 deletions.
16 changes: 9 additions & 7 deletions src/controller/event/handler/auditlog/auditlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ package auditlog

import (
"context"
"fmt"

"github.com/goharbor/harbor/src/controller/event"
evtModel "github.com/goharbor/harbor/src/controller/event/model"
"github.com/goharbor/harbor/src/lib/config"
"github.com/goharbor/harbor/src/lib/log"
"github.com/goharbor/harbor/src/pkg/audit"
am "github.com/goharbor/harbor/src/pkg/audit/model"
"github.com/goharbor/harbor/src/pkg/auditext"
am "github.com/goharbor/harbor/src/pkg/auditext/model"
)

// Handler - audit log handler
Expand All @@ -30,7 +32,7 @@ type Handler struct {

// AuditResolver - interface to resolve to AuditLog
type AuditResolver interface {
ResolveToAuditLog() (*am.AuditLog, error)
ResolveToAuditLog() (*am.AuditLogExt, error)
}

// Name ...
Expand All @@ -40,13 +42,13 @@ func (h *Handler) Name() string {

// Handle ...
func (h *Handler) Handle(ctx context.Context, value interface{}) error {
var auditLog *am.AuditLog
var auditLog *am.AuditLogExt
var addAuditLog bool
switch v := value.(type) {
case *event.PushArtifactEvent, *event.DeleteArtifactEvent,
*event.DeleteRepositoryEvent, *event.CreateProjectEvent, *event.DeleteProjectEvent,
*event.DeleteTagEvent, *event.CreateTagEvent,
*event.CreateRobotEvent, *event.DeleteRobotEvent:
*event.CreateRobotEvent, *event.DeleteRobotEvent, *evtModel.CommonEvent:
addAuditLog = true
case *event.PullArtifactEvent:
addAuditLog = !config.PullAuditLogDisable(ctx)
Expand All @@ -62,8 +64,8 @@ func (h *Handler) Handle(ctx context.Context, value interface{}) error {
return err
}
auditLog = al
if auditLog != nil {
_, err := audit.Mgr.Create(ctx, auditLog)
if auditLog != nil && config.AuditLogEventEnabled(ctx, fmt.Sprintf("%v_%v", auditLog.Operation, auditLog.ResourceType)) {
_, err := auditext.Mgr.Create(ctx, auditLog)
if err != nil {
log.Debugf("add audit log err: %v", err)
}
Expand Down
1 change: 1 addition & 0 deletions src/controller/event/handler/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func init() {
_ = notifier.Subscribe(event.TopicDeleteTag, &auditlog.Handler{})
_ = notifier.Subscribe(event.TopicCreateRobot, &auditlog.Handler{})
_ = notifier.Subscribe(event.TopicDeleteRobot, &auditlog.Handler{})
_ = notifier.Subscribe(event.TopicCommonEvent, &auditlog.Handler{})

// internal
_ = notifier.Subscribe(event.TopicPullArtifact, &internal.ArtifactEventHandler{})
Expand Down
2 changes: 2 additions & 0 deletions src/controller/event/metadata/commonevent/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ type Metadata struct {
ResponseLocation string
// ResourceName
ResourceName string
// Payload
Payload string
}

// Resolve parse the audit information from CommonEventMetadata
Expand Down
36 changes: 35 additions & 1 deletion src/controller/event/model/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@

package model

import "github.com/goharbor/harbor/src/pkg/retention/policy/rule"
import (
"time"

"github.com/goharbor/harbor/src/pkg/auditext/model"
"github.com/goharbor/harbor/src/pkg/retention/policy/rule"
)

// Replication describes replication infos
type Replication struct {
Expand Down Expand Up @@ -80,3 +85,32 @@ type Scan struct {
// ScanType the scan type
ScanType string `json:"scan_type,omitempty"`
}

// CommonEvent ...
type CommonEvent struct {
Operator string
ProjectID int64
OcurrAt time.Time
Operation string
Payload string
SourceIP string
ResourceType string
ResourceName string
OperationDescription string
OperationResult bool
}

// ResolveToAuditLog ...
func (c *CommonEvent) ResolveToAuditLog() (*model.AuditLogExt, error) {
auditLog := &model.AuditLogExt{
ProjectID: c.ProjectID,
OpTime: c.OcurrAt,
Operation: c.Operation,
Username: c.Operator,
ResourceType: c.ResourceType,
Resource: c.ResourceName,
OperationDescription: c.OperationDescription,
OperationResult: c.OperationResult,
}
return auditLog, nil
}
178 changes: 99 additions & 79 deletions src/controller/event/topic.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"github.com/goharbor/harbor/src/common/rbac"
"github.com/goharbor/harbor/src/lib/selector"
"github.com/goharbor/harbor/src/pkg/artifact"
"github.com/goharbor/harbor/src/pkg/audit/model"
"github.com/goharbor/harbor/src/pkg/auditext/model"
proModels "github.com/goharbor/harbor/src/pkg/project/models"
robotModel "github.com/goharbor/harbor/src/pkg/robot/model"
v1 "github.com/goharbor/harbor/src/pkg/scan/rest/v1"
Expand Down Expand Up @@ -50,6 +50,7 @@ const (
TopicTagRetention = "TAG_RETENTION"
TopicCreateRobot = "CREATE_ROBOT"
TopicDeleteRobot = "DELETE_ROBOT"
TopicCommonEvent = "COMMON_API"
)

// CreateProjectEvent is the creating project event
Expand All @@ -62,14 +63,16 @@ type CreateProjectEvent struct {
}

// ResolveToAuditLog ...
func (c *CreateProjectEvent) ResolveToAuditLog() (*model.AuditLog, error) {
auditLog := &model.AuditLog{
ProjectID: c.ProjectID,
OpTime: c.OccurAt,
Operation: rbac.ActionCreate.String(),
Username: c.Operator,
ResourceType: "project",
Resource: c.Project}
func (c *CreateProjectEvent) ResolveToAuditLog() (*model.AuditLogExt, error) {
auditLog := &model.AuditLogExt{
ProjectID: c.ProjectID,
OpTime: c.OccurAt,
Operation: rbac.ActionCreate.String(),
Username: c.Operator,
ResourceType: "project",
OperationResult: true,
OperationDescription: fmt.Sprintf("create project: %s", c.Project),
Resource: c.Project}
return auditLog, nil
}

Expand All @@ -88,14 +91,16 @@ type DeleteProjectEvent struct {
}

// ResolveToAuditLog ...
func (d *DeleteProjectEvent) ResolveToAuditLog() (*model.AuditLog, error) {
auditLog := &model.AuditLog{
ProjectID: d.ProjectID,
OpTime: d.OccurAt,
Operation: rbac.ActionDelete.String(),
Username: d.Operator,
ResourceType: "project",
Resource: d.Project}
func (d *DeleteProjectEvent) ResolveToAuditLog() (*model.AuditLogExt, error) {
auditLog := &model.AuditLogExt{
ProjectID: d.ProjectID,
OpTime: d.OccurAt,
Operation: rbac.ActionDelete.String(),
Username: d.Operator,
ResourceType: "project",
OperationResult: true,
OperationDescription: fmt.Sprintf("delete project: %s", d.Project),
Resource: d.Project}
return auditLog, nil
}

Expand All @@ -114,14 +119,16 @@ type DeleteRepositoryEvent struct {
}

// ResolveToAuditLog ...
func (d *DeleteRepositoryEvent) ResolveToAuditLog() (*model.AuditLog, error) {
auditLog := &model.AuditLog{
ProjectID: d.ProjectID,
OpTime: d.OccurAt,
Operation: rbac.ActionDelete.String(),
Username: d.Operator,
ResourceType: "repository",
Resource: d.Repository,
func (d *DeleteRepositoryEvent) ResolveToAuditLog() (*model.AuditLogExt, error) {
auditLog := &model.AuditLogExt{
ProjectID: d.ProjectID,
OpTime: d.OccurAt,
Operation: rbac.ActionDelete.String(),
Username: d.Operator,
ResourceType: "repository",
OperationResult: true,
OperationDescription: fmt.Sprintf("delete repository: %s", d.Repository),
Resource: d.Repository,
}
return auditLog, nil
}
Expand Down Expand Up @@ -154,13 +161,15 @@ type PushArtifactEvent struct {
}

// ResolveToAuditLog ...
func (p *PushArtifactEvent) ResolveToAuditLog() (*model.AuditLog, error) {
auditLog := &model.AuditLog{
ProjectID: p.Artifact.ProjectID,
OpTime: p.OccurAt,
Operation: rbac.ActionCreate.String(),
Username: p.Operator,
ResourceType: "artifact"}
func (p *PushArtifactEvent) ResolveToAuditLog() (*model.AuditLogExt, error) {
auditLog := &model.AuditLogExt{
ProjectID: p.Artifact.ProjectID,
OpTime: p.OccurAt,
Operation: rbac.ActionCreate.String(),
Username: p.Operator,
OperationResult: true,
OperationDescription: fmt.Sprintf("push artifact: %s@%s", p.Artifact.RepositoryName, p.Artifact.Digest),
ResourceType: "artifact"}

if len(p.Tags) == 0 {
auditLog.Resource = fmt.Sprintf("%s@%s",
Expand All @@ -183,13 +192,15 @@ type PullArtifactEvent struct {
}

// ResolveToAuditLog ...
func (p *PullArtifactEvent) ResolveToAuditLog() (*model.AuditLog, error) {
auditLog := &model.AuditLog{
ProjectID: p.Artifact.ProjectID,
OpTime: p.OccurAt,
Operation: rbac.ActionPull.String(),
Username: p.Operator,
ResourceType: "artifact"}
func (p *PullArtifactEvent) ResolveToAuditLog() (*model.AuditLogExt, error) {
auditLog := &model.AuditLogExt{
ProjectID: p.Artifact.ProjectID,
OpTime: p.OccurAt,
Operation: rbac.ActionPull.String(),
Username: p.Operator,
OperationResult: true,
OperationDescription: fmt.Sprintf("pull artifact: %s@%s", p.Artifact.RepositoryName, p.Artifact.Digest),
ResourceType: "artifact"}

if len(p.Tags) == 0 {
auditLog.Resource = fmt.Sprintf("%s@%s",
Expand Down Expand Up @@ -219,14 +230,16 @@ type DeleteArtifactEvent struct {
}

// ResolveToAuditLog ...
func (d *DeleteArtifactEvent) ResolveToAuditLog() (*model.AuditLog, error) {
auditLog := &model.AuditLog{
ProjectID: d.Artifact.ProjectID,
OpTime: d.OccurAt,
Operation: rbac.ActionDelete.String(),
Username: d.Operator,
ResourceType: "artifact",
Resource: fmt.Sprintf("%s@%s", d.Artifact.RepositoryName, d.Artifact.Digest)}
func (d *DeleteArtifactEvent) ResolveToAuditLog() (*model.AuditLogExt, error) {
auditLog := &model.AuditLogExt{
ProjectID: d.Artifact.ProjectID,
OpTime: d.OccurAt,
Operation: rbac.ActionDelete.String(),
Username: d.Operator,
ResourceType: "artifact",
OperationResult: true,
OperationDescription: fmt.Sprintf("delete artifact: %s@%s", d.Artifact.RepositoryName, d.Artifact.Digest),
Resource: fmt.Sprintf("%s@%s", d.Artifact.RepositoryName, d.Artifact.Digest)}
return auditLog, nil
}

Expand All @@ -246,14 +259,16 @@ type CreateTagEvent struct {
}

// ResolveToAuditLog ...
func (c *CreateTagEvent) ResolveToAuditLog() (*model.AuditLog, error) {
auditLog := &model.AuditLog{
ProjectID: c.AttachedArtifact.ProjectID,
OpTime: c.OccurAt,
Operation: rbac.ActionCreate.String(),
Username: c.Operator,
ResourceType: "tag",
Resource: fmt.Sprintf("%s:%s", c.Repository, c.Tag)}
func (c *CreateTagEvent) ResolveToAuditLog() (*model.AuditLogExt, error) {
auditLog := &model.AuditLogExt{
ProjectID: c.AttachedArtifact.ProjectID,
OpTime: c.OccurAt,
Operation: rbac.ActionCreate.String(),
Username: c.Operator,
ResourceType: "tag",
OperationResult: true,
OperationDescription: fmt.Sprintf("create tag: %s:%s", c.Repository, c.Tag),
Resource: fmt.Sprintf("%s:%s", c.Repository, c.Tag)}
return auditLog, nil
}

Expand All @@ -275,14 +290,15 @@ type DeleteTagEvent struct {
}

// ResolveToAuditLog ...
func (d *DeleteTagEvent) ResolveToAuditLog() (*model.AuditLog, error) {
auditLog := &model.AuditLog{
ProjectID: d.AttachedArtifact.ProjectID,
OpTime: d.OccurAt,
Operation: rbac.ActionDelete.String(),
Username: d.Operator,
ResourceType: "tag",
Resource: fmt.Sprintf("%s:%s", d.Repository, d.Tag)}
func (d *DeleteTagEvent) ResolveToAuditLog() (*model.AuditLogExt, error) {
auditLog := &model.AuditLogExt{
ProjectID: d.AttachedArtifact.ProjectID,
OpTime: d.OccurAt,
Operation: rbac.ActionDelete.String(),
Username: d.Operator,
ResourceType: "tag",
OperationResult: true,
Resource: fmt.Sprintf("%s:%s", d.Repository, d.Tag)}
return auditLog, nil
}

Expand Down Expand Up @@ -385,14 +401,16 @@ type CreateRobotEvent struct {
}

// ResolveToAuditLog ...
func (c *CreateRobotEvent) ResolveToAuditLog() (*model.AuditLog, error) {
auditLog := &model.AuditLog{
ProjectID: c.Robot.ProjectID,
OpTime: c.OccurAt,
Operation: rbac.ActionCreate.String(),
Username: c.Operator,
ResourceType: "robot",
Resource: c.Robot.Name}
func (c *CreateRobotEvent) ResolveToAuditLog() (*model.AuditLogExt, error) {
auditLog := &model.AuditLogExt{
ProjectID: c.Robot.ProjectID,
OpTime: c.OccurAt,
Operation: rbac.ActionCreate.String(),
Username: c.Operator,
ResourceType: "robot",
OperationResult: true,
OperationDescription: fmt.Sprintf("create robot: %s", c.Robot.Name),
Resource: c.Robot.Name}
return auditLog, nil
}

Expand All @@ -410,14 +428,16 @@ type DeleteRobotEvent struct {
}

// ResolveToAuditLog ...
func (c *DeleteRobotEvent) ResolveToAuditLog() (*model.AuditLog, error) {
auditLog := &model.AuditLog{
ProjectID: c.Robot.ProjectID,
OpTime: c.OccurAt,
Operation: rbac.ActionDelete.String(),
Username: c.Operator,
ResourceType: "robot",
Resource: c.Robot.Name}
func (c *DeleteRobotEvent) ResolveToAuditLog() (*model.AuditLogExt, error) {
auditLog := &model.AuditLogExt{
ProjectID: c.Robot.ProjectID,
OpTime: c.OccurAt,
Operation: rbac.ActionDelete.String(),
Username: c.Operator,
ResourceType: "robot",
OperationResult: true,
OperationDescription: fmt.Sprintf("delete robot: %s", c.Robot.Name),
Resource: c.Robot.Name}
return auditLog, nil
}

Expand Down
1 change: 1 addition & 0 deletions src/core/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import (
_ "github.com/goharbor/harbor/src/pkg/accessory/model/sbom"
_ "github.com/goharbor/harbor/src/pkg/accessory/model/subject"
"github.com/goharbor/harbor/src/pkg/audit"
_ "github.com/goharbor/harbor/src/pkg/auditext/event/login"
dbCfg "github.com/goharbor/harbor/src/pkg/config/db"
_ "github.com/goharbor/harbor/src/pkg/config/inmemory"
"github.com/goharbor/harbor/src/pkg/notification"
Expand Down
3 changes: 3 additions & 0 deletions src/lib/config/userconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,9 @@ func BannerMessage(ctx context.Context) string {

// AuditLogEventEnabled returns the audit log enabled setting for a specific event_type, such as delete_user, create_user
func AuditLogEventEnabled(ctx context.Context, eventType string) bool {
if DefaultMgr() == nil || DefaultMgr().Get(ctx, common.AuditLogEventsDisabled) == nil {
return true
}
disableListStr := DefaultMgr().Get(ctx, common.AuditLogEventsDisabled).GetString()
disableList := strings.Split(disableListStr, ",")
for _, t := range disableList {
Expand Down
Loading

0 comments on commit 9cc5065

Please sign in to comment.