mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-22 10:15:35 +01:00
Merge branch 'main' into main
This commit is contained in:
commit
750ddfc6e0
@ -45,7 +45,8 @@ func (h *Handler) Handle(ctx context.Context, value interface{}) error {
|
|||||||
switch v := value.(type) {
|
switch v := value.(type) {
|
||||||
case *event.PushArtifactEvent, *event.DeleteArtifactEvent,
|
case *event.PushArtifactEvent, *event.DeleteArtifactEvent,
|
||||||
*event.DeleteRepositoryEvent, *event.CreateProjectEvent, *event.DeleteProjectEvent,
|
*event.DeleteRepositoryEvent, *event.CreateProjectEvent, *event.DeleteProjectEvent,
|
||||||
*event.DeleteTagEvent, *event.CreateTagEvent:
|
*event.DeleteTagEvent, *event.CreateTagEvent,
|
||||||
|
*event.CreateRobotEvent, *event.DeleteRobotEvent:
|
||||||
addAuditLog = true
|
addAuditLog = true
|
||||||
case *event.PullArtifactEvent:
|
case *event.PullArtifactEvent:
|
||||||
addAuditLog = !config.PullAuditLogDisable(ctx)
|
addAuditLog = !config.PullAuditLogDisable(ctx)
|
||||||
|
@ -65,6 +65,8 @@ func init() {
|
|||||||
_ = notifier.Subscribe(event.TopicDeleteRepository, &auditlog.Handler{})
|
_ = notifier.Subscribe(event.TopicDeleteRepository, &auditlog.Handler{})
|
||||||
_ = notifier.Subscribe(event.TopicCreateTag, &auditlog.Handler{})
|
_ = notifier.Subscribe(event.TopicCreateTag, &auditlog.Handler{})
|
||||||
_ = notifier.Subscribe(event.TopicDeleteTag, &auditlog.Handler{})
|
_ = notifier.Subscribe(event.TopicDeleteTag, &auditlog.Handler{})
|
||||||
|
_ = notifier.Subscribe(event.TopicCreateRobot, &auditlog.Handler{})
|
||||||
|
_ = notifier.Subscribe(event.TopicDeleteRobot, &auditlog.Handler{})
|
||||||
|
|
||||||
// internal
|
// internal
|
||||||
_ = notifier.Subscribe(event.TopicPullArtifact, &internal.ArtifactEventHandler{})
|
_ = notifier.Subscribe(event.TopicPullArtifact, &internal.ArtifactEventHandler{})
|
||||||
|
73
src/controller/event/metadata/robot.go
Normal file
73
src/controller/event/metadata/robot.go
Normal file
@ -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()
|
||||||
|
}
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
data.Robot.Name = fmt.Sprintf("%s%s", config.RobotPrefix(d.Ctx), data.Robot.Name)
|
||||||
|
event.Topic = event2.TopicDeleteRobot
|
||||||
|
event.Data = data
|
||||||
|
return nil
|
||||||
|
}
|
83
src/controller/event/metadata/robot_test.go
Normal file
83
src/controller/event/metadata/robot_test.go
Normal file
@ -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{})
|
||||||
|
}
|
@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/goharbor/harbor/src/pkg/artifact"
|
"github.com/goharbor/harbor/src/pkg/artifact"
|
||||||
"github.com/goharbor/harbor/src/pkg/audit/model"
|
"github.com/goharbor/harbor/src/pkg/audit/model"
|
||||||
proModels "github.com/goharbor/harbor/src/pkg/project/models"
|
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"
|
v1 "github.com/goharbor/harbor/src/pkg/scan/rest/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -47,6 +48,8 @@ const (
|
|||||||
TopicReplication = "REPLICATION"
|
TopicReplication = "REPLICATION"
|
||||||
TopicArtifactLabeled = "ARTIFACT_LABELED"
|
TopicArtifactLabeled = "ARTIFACT_LABELED"
|
||||||
TopicTagRetention = "TAG_RETENTION"
|
TopicTagRetention = "TAG_RETENTION"
|
||||||
|
TopicCreateRobot = "CREATE_ROBOT"
|
||||||
|
TopicDeleteRobot = "DELETE_ROBOT"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateProjectEvent is the creating project event
|
// CreateProjectEvent is the creating project event
|
||||||
@ -369,3 +372,53 @@ func (r *RetentionEvent) String() string {
|
|||||||
return fmt.Sprintf("TaskID-%d Status-%s Deleted-%s OccurAt-%s",
|
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"))
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
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"))
|
||||||
|
}
|
||||||
|
@ -23,12 +23,14 @@ import (
|
|||||||
|
|
||||||
rbac_project "github.com/goharbor/harbor/src/common/rbac/project"
|
rbac_project "github.com/goharbor/harbor/src/common/rbac/project"
|
||||||
"github.com/goharbor/harbor/src/common/utils"
|
"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/config"
|
||||||
"github.com/goharbor/harbor/src/lib/errors"
|
"github.com/goharbor/harbor/src/lib/errors"
|
||||||
"github.com/goharbor/harbor/src/lib/log"
|
"github.com/goharbor/harbor/src/lib/log"
|
||||||
"github.com/goharbor/harbor/src/lib/q"
|
"github.com/goharbor/harbor/src/lib/q"
|
||||||
"github.com/goharbor/harbor/src/lib/retry"
|
"github.com/goharbor/harbor/src/lib/retry"
|
||||||
"github.com/goharbor/harbor/src/pkg"
|
"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/permission/types"
|
||||||
"github.com/goharbor/harbor/src/pkg/project"
|
"github.com/goharbor/harbor/src/pkg/project"
|
||||||
"github.com/goharbor/harbor/src/pkg/rbac"
|
"github.com/goharbor/harbor/src/pkg/rbac"
|
||||||
@ -121,7 +123,7 @@ func (d *controller) Create(ctx context.Context, r *Robot) (int64, string, error
|
|||||||
if r.Level == LEVELPROJECT {
|
if r.Level == LEVELPROJECT {
|
||||||
name = fmt.Sprintf("%s+%s", r.ProjectName, r.Name)
|
name = fmt.Sprintf("%s+%s", r.ProjectName, r.Name)
|
||||||
}
|
}
|
||||||
robotID, err := d.robotMgr.Create(ctx, &model.Robot{
|
rCreate := &model.Robot{
|
||||||
Name: name,
|
Name: name,
|
||||||
Description: r.Description,
|
Description: r.Description,
|
||||||
ProjectID: r.ProjectID,
|
ProjectID: r.ProjectID,
|
||||||
@ -130,7 +132,8 @@ func (d *controller) Create(ctx context.Context, r *Robot) (int64, string, error
|
|||||||
Duration: r.Duration,
|
Duration: r.Duration,
|
||||||
Salt: salt,
|
Salt: salt,
|
||||||
Visible: r.Visible,
|
Visible: r.Visible,
|
||||||
})
|
}
|
||||||
|
robotID, err := d.robotMgr.Create(ctx, rCreate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, "", err
|
return 0, "", err
|
||||||
}
|
}
|
||||||
@ -138,17 +141,31 @@ func (d *controller) Create(ctx context.Context, r *Robot) (int64, string, error
|
|||||||
if err := d.createPermission(ctx, r); err != nil {
|
if err := d.createPermission(ctx, r); err != nil {
|
||||||
return 0, "", err
|
return 0, "", err
|
||||||
}
|
}
|
||||||
|
// fire event
|
||||||
|
notification.AddEvent(ctx, &metadata.CreateRobotEventMetadata{
|
||||||
|
Ctx: ctx,
|
||||||
|
Robot: rCreate,
|
||||||
|
})
|
||||||
return robotID, pwd, nil
|
return robotID, pwd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete ...
|
// Delete ...
|
||||||
func (d *controller) Delete(ctx context.Context, id int64) error {
|
func (d *controller) Delete(ctx context.Context, id int64) error {
|
||||||
|
rDelete, err := d.robotMgr.Get(ctx, id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := d.robotMgr.Delete(ctx, id); err != nil {
|
if err := d.robotMgr.Delete(ctx, id); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := d.rbacMgr.DeletePermissionsByRole(ctx, ROBOTTYPE, id); err != nil {
|
if err := d.rbacMgr.DeletePermissionsByRole(ctx, ROBOTTYPE, id); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// fire event
|
||||||
|
notification.AddEvent(ctx, &metadata.DeleteRobotEventMetadata{
|
||||||
|
Ctx: ctx,
|
||||||
|
Robot: rDelete,
|
||||||
|
})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +145,12 @@ func (suite *ControllerTestSuite) TestDelete() {
|
|||||||
c := controller{robotMgr: robotMgr, rbacMgr: rbacMgr, proMgr: projectMgr}
|
c := controller{robotMgr: robotMgr, rbacMgr: rbacMgr, proMgr: projectMgr}
|
||||||
ctx := context.TODO()
|
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)
|
robotMgr.On("Delete", mock.Anything, mock.Anything).Return(nil)
|
||||||
rbacMgr.On("DeletePermissionsByRole", mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
rbacMgr.On("DeletePermissionsByRole", mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user