Skip to content

Commit

Permalink
enable audit log for robot
Browse files Browse the repository at this point in the history
1, add creation audit log for robot account
2, add deletion audit log for robot account

Signed-off-by: wang yan <[email protected]>
  • Loading branch information
wy65701436 committed Aug 14, 2024
1 parent 907709f commit cf4e41f
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 3 deletions.
3 changes: 2 additions & 1 deletion src/controller/event/handler/auditlog/auditlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ func (h *Handler) Handle(ctx context.Context, value interface{}) error {
switch v := value.(type) {
case *event.PushArtifactEvent, *event.DeleteArtifactEvent,
*event.DeleteRepositoryEvent, *event.CreateProjectEvent, *event.DeleteProjectEvent,
*event.DeleteTagEvent, *event.CreateTagEvent:
*event.DeleteTagEvent, *event.CreateTagEvent,
*event.CreateRobotEvent, *event.DeleteRobotEvent:
addAuditLog = true
case *event.PullArtifactEvent:
addAuditLog = !config.PullAuditLogDisable(ctx)
Expand Down
2 changes: 2 additions & 0 deletions src/controller/event/handler/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ func init() {
_ = notifier.Subscribe(event.TopicDeleteRepository, &auditlog.Handler{})
_ = notifier.Subscribe(event.TopicCreateTag, &auditlog.Handler{})
_ = notifier.Subscribe(event.TopicDeleteTag, &auditlog.Handler{})
_ = notifier.Subscribe(event.TopicCreateRobot, &auditlog.Handler{})
_ = notifier.Subscribe(event.TopicDeleteRobot, &auditlog.Handler{})

Check warning on line 69 in src/controller/event/handler/init.go

View check run for this annotation

Codecov / codecov/patch

src/controller/event/handler/init.go#L68-L69

Added lines #L68 - L69 were not covered by tests

// internal
_ = notifier.Subscribe(event.TopicPullArtifact, &internal.ArtifactEventHandler{})
Expand Down
73 changes: 73 additions & 0 deletions src/controller/event/metadata/robot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// 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 metadata

import (
"context"
"fmt"
"time"

"github.com/goharbor/harbor/src/common/security"
event2 "github.com/goharbor/harbor/src/controller/event"
"github.com/goharbor/harbor/src/lib/config"
"github.com/goharbor/harbor/src/pkg/notifier/event"
"github.com/goharbor/harbor/src/pkg/robot/model"
)

// CreateRobotEventMetadata is the metadata from which the create robot event can be resolved
type CreateRobotEventMetadata struct {
Ctx context.Context
Robot *model.Robot
}

// Resolve to the event from the metadata
func (c *CreateRobotEventMetadata) Resolve(event *event.Event) error {
data := &event2.CreateRobotEvent{
EventType: event2.TopicCreateRobot,
Robot: c.Robot,
OccurAt: time.Now(),
}
cx, exist := security.FromContext(c.Ctx)
if exist {
data.Operator = cx.GetUsername()
}

Check warning on line 45 in src/controller/event/metadata/robot.go

View check run for this annotation

Codecov / codecov/patch

src/controller/event/metadata/robot.go#L44-L45

Added lines #L44 - L45 were not covered by tests
data.Robot.Name = fmt.Sprintf("%s%s", config.RobotPrefix(c.Ctx), data.Robot.Name)
event.Topic = event2.TopicCreateRobot
event.Data = data
return nil
}

// DeleteRobotEventMetadata is the metadata from which the delete robot event can be resolved
type DeleteRobotEventMetadata struct {
Ctx context.Context
Robot *model.Robot
}

// Resolve to the event from the metadata
func (d *DeleteRobotEventMetadata) Resolve(event *event.Event) error {
data := &event2.DeleteRobotEvent{
EventType: event2.TopicDeleteRobot,
Robot: d.Robot,
OccurAt: time.Now(),
}
cx, exist := security.FromContext(d.Ctx)
if exist {
data.Operator = cx.GetUsername()
}

Check warning on line 68 in src/controller/event/metadata/robot.go

View check run for this annotation

Codecov / codecov/patch

src/controller/event/metadata/robot.go#L67-L68

Added lines #L67 - L68 were not covered by tests
data.Robot.Name = fmt.Sprintf("%s%s", config.RobotPrefix(d.Ctx), data.Robot.Name)
event.Topic = event2.TopicDeleteRobot
event.Data = data
return nil
}
83 changes: 83 additions & 0 deletions src/controller/event/metadata/robot_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// 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 metadata

import (
"context"
"testing"

"github.com/stretchr/testify/suite"

"github.com/goharbor/harbor/src/common"
event2 "github.com/goharbor/harbor/src/controller/event"
"github.com/goharbor/harbor/src/lib/config"
_ "github.com/goharbor/harbor/src/pkg/config/inmemory"
"github.com/goharbor/harbor/src/pkg/notifier/event"
"github.com/goharbor/harbor/src/pkg/robot/model"
)

type robotEventTestSuite struct {
suite.Suite
}

func (t *tagEventTestSuite) TestResolveOfCreateRobotEventMetadata() {
cfg := map[string]interface{}{
common.RobotPrefix: "robot$",
}
config.InitWithSettings(cfg)

e := &event.Event{}
metadata := &CreateRobotEventMetadata{
Ctx: context.Background(),
Robot: &model.Robot{
ID: 1,
Name: "test",
},
}
err := metadata.Resolve(e)
t.Require().Nil(err)
t.Equal(event2.TopicCreateRobot, e.Topic)
t.Require().NotNil(e.Data)
data, ok := e.Data.(*event2.CreateRobotEvent)
t.Require().True(ok)
t.Equal(int64(1), data.Robot.ID)
t.Equal("robot$test", data.Robot.Name)
}

func (t *tagEventTestSuite) TestResolveOfDeleteRobotEventMetadata() {
cfg := map[string]interface{}{
common.RobotPrefix: "robot$",
}
config.InitWithSettings(cfg)

e := &event.Event{}
metadata := &DeleteRobotEventMetadata{
Ctx: context.Background(),
Robot: &model.Robot{
ID: 1,
},
}
err := metadata.Resolve(e)
t.Require().Nil(err)
t.Equal(event2.TopicDeleteRobot, e.Topic)
t.Require().NotNil(e.Data)
data, ok := e.Data.(*event2.DeleteRobotEvent)
t.Require().True(ok)
t.Equal(int64(1), data.Robot.ID)
}

func TestRobotEventTestSuite(t *testing.T) {
suite.Run(t, &robotEventTestSuite{})
}
53 changes: 53 additions & 0 deletions src/controller/event/topic.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/goharbor/harbor/src/pkg/artifact"
"github.com/goharbor/harbor/src/pkg/audit/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 All @@ -47,6 +48,8 @@ const (
TopicReplication = "REPLICATION"
TopicArtifactLabeled = "ARTIFACT_LABELED"
TopicTagRetention = "TAG_RETENTION"
TopicCreateRobot = "CREATE_ROBOT"
TopicDeleteRobot = "DELETE_ROBOT"
)

// CreateProjectEvent is the creating project event
Expand Down Expand Up @@ -369,3 +372,53 @@ func (r *RetentionEvent) String() string {
return fmt.Sprintf("TaskID-%d Status-%s Deleted-%s OccurAt-%s",
r.TaskID, r.Status, candidates, r.OccurAt.Format("2006-01-02 15:04:05"))
}

// CreateRobotEvent is the creating robot event
type CreateRobotEvent struct {
EventType string
Robot *robotModel.Robot
Operator string
OccurAt time.Time
}

// 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}
return auditLog, nil

Check warning on line 393 in src/controller/event/topic.go

View check run for this annotation

Codecov / codecov/patch

src/controller/event/topic.go#L385-L393

Added lines #L385 - L393 were not covered by tests
}

func (c *CreateRobotEvent) String() string {
return fmt.Sprintf("Name-%s Operator-%s OccurAt-%s",
c.Robot.Name, c.Operator, c.OccurAt.Format("2006-01-02 15:04:05"))

Check warning on line 398 in src/controller/event/topic.go

View check run for this annotation

Codecov / codecov/patch

src/controller/event/topic.go#L396-L398

Added lines #L396 - L398 were not covered by tests
}

// DeleteRobotEvent is the deleting robot event
type DeleteRobotEvent struct {
EventType string
Robot *robotModel.Robot
Operator string
OccurAt time.Time
}

// 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}
return auditLog, nil

Check warning on line 418 in src/controller/event/topic.go

View check run for this annotation

Codecov / codecov/patch

src/controller/event/topic.go#L410-L418

Added lines #L410 - L418 were not covered by tests
}

func (c *DeleteRobotEvent) String() string {
return fmt.Sprintf("Name-%s Operator-%s OccurAt-%s",
c.Robot.Name, c.Operator, c.OccurAt.Format("2006-01-02 15:04:05"))

Check warning on line 423 in src/controller/event/topic.go

View check run for this annotation

Codecov / codecov/patch

src/controller/event/topic.go#L421-L423

Added lines #L421 - L423 were not covered by tests
}
21 changes: 19 additions & 2 deletions src/controller/robot/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ import (

rbac_project "github.com/goharbor/harbor/src/common/rbac/project"
"github.com/goharbor/harbor/src/common/utils"
"github.com/goharbor/harbor/src/controller/event/metadata"
"github.com/goharbor/harbor/src/lib/config"
"github.com/goharbor/harbor/src/lib/errors"
"github.com/goharbor/harbor/src/lib/log"
"github.com/goharbor/harbor/src/lib/q"
"github.com/goharbor/harbor/src/lib/retry"
"github.com/goharbor/harbor/src/pkg"
"github.com/goharbor/harbor/src/pkg/notification"
"github.com/goharbor/harbor/src/pkg/permission/types"
"github.com/goharbor/harbor/src/pkg/project"
"github.com/goharbor/harbor/src/pkg/rbac"
Expand Down Expand Up @@ -121,7 +123,7 @@ func (d *controller) Create(ctx context.Context, r *Robot) (int64, string, error
if r.Level == LEVELPROJECT {
name = fmt.Sprintf("%s+%s", r.ProjectName, r.Name)
}
robotID, err := d.robotMgr.Create(ctx, &model.Robot{
rCreate := &model.Robot{
Name: name,
Description: r.Description,
ProjectID: r.ProjectID,
Expand All @@ -130,25 +132,40 @@ func (d *controller) Create(ctx context.Context, r *Robot) (int64, string, error
Duration: r.Duration,
Salt: salt,
Visible: r.Visible,
})
}
robotID, err := d.robotMgr.Create(ctx, rCreate)
if err != nil {
return 0, "", err
}
r.ID = robotID
if err := d.createPermission(ctx, r); err != nil {
return 0, "", err
}
// fire event
notification.AddEvent(ctx, &metadata.CreateRobotEventMetadata{
Ctx: ctx,
Robot: rCreate,
})
return robotID, pwd, nil
}

// Delete ...
func (d *controller) Delete(ctx context.Context, id int64) error {
rDelete, err := d.robotMgr.Get(ctx, id)
if err != nil {
return err
}

Check warning on line 157 in src/controller/robot/controller.go

View check run for this annotation

Codecov / codecov/patch

src/controller/robot/controller.go#L156-L157

Added lines #L156 - L157 were not covered by tests
if err := d.robotMgr.Delete(ctx, id); err != nil {
return err
}
if err := d.rbacMgr.DeletePermissionsByRole(ctx, ROBOTTYPE, id); err != nil {
return err
}
// fire event
notification.AddEvent(ctx, &metadata.DeleteRobotEventMetadata{
Ctx: ctx,
Robot: rDelete,
})
return nil
}

Expand Down
6 changes: 6 additions & 0 deletions src/controller/robot/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@ func (suite *ControllerTestSuite) TestDelete() {
c := controller{robotMgr: robotMgr, rbacMgr: rbacMgr, proMgr: projectMgr}
ctx := context.TODO()

robotMgr.On("Get", mock.Anything, mock.Anything).Return(&model.Robot{
Name: "library+test",
Description: "test get method",
ProjectID: 1,
Secret: utils.RandStringBytes(10),
}, nil)
robotMgr.On("Delete", mock.Anything, mock.Anything).Return(nil)
rbacMgr.On("DeletePermissionsByRole", mock.Anything, mock.Anything, mock.Anything).Return(nil)

Expand Down

0 comments on commit cf4e41f

Please sign in to comment.