125 lines
3.0 KiB
Go
125 lines
3.0 KiB
Go
package aduit
|
||
|
||
import (
|
||
"context"
|
||
|
||
"github.com/emicklei/go-restful/v3"
|
||
"github.com/infraboard/mcube/v2/ioc"
|
||
"github.com/infraboard/mcube/v2/ioc/config/application"
|
||
"github.com/infraboard/mcube/v2/ioc/config/gorestful"
|
||
ioc_kafka "github.com/infraboard/mcube/v2/ioc/config/kafka"
|
||
"github.com/infraboard/mcube/v2/ioc/config/log"
|
||
"github.com/infraboard/modules/iam/apps/endpoint"
|
||
"github.com/infraboard/modules/iam/apps/token"
|
||
"github.com/rs/zerolog"
|
||
"github.com/segmentio/kafka-go"
|
||
"gitlab.com/go-course-project/go17/devcloud-mini/maudit/apps/event"
|
||
)
|
||
|
||
func init() {
|
||
ioc.Config().Registry(&auditor{
|
||
Topic: "maudit_new",
|
||
})
|
||
}
|
||
|
||
func Audit(v bool) (string, bool) {
|
||
return event.META_AUDIT_KEY, v
|
||
}
|
||
|
||
type auditor struct {
|
||
ioc.ObjectImpl
|
||
|
||
log *zerolog.Logger
|
||
|
||
// 当前这个消费者 配置的topic
|
||
Topic string `toml:"topic" json:"topic" yaml:"topic" env:"TOPIC"`
|
||
//
|
||
wirter *kafka.Writer
|
||
}
|
||
|
||
func (a *auditor) Name() string {
|
||
return "auditor"
|
||
}
|
||
|
||
func (a *auditor) Init() error {
|
||
a.log = log.Sub("mauditor")
|
||
a.log.Debug().Msgf("maduit topic name: %s", a.Topic)
|
||
a.wirter = ioc_kafka.Producer(a.Topic)
|
||
|
||
// 添加到中间件, 加到Root Router里面
|
||
ws := gorestful.RootRouter()
|
||
ws.Filter(a.Audit())
|
||
return nil
|
||
}
|
||
|
||
// 补充中间件函数逻辑
|
||
func (a *auditor) Audit() restful.FilterFunction {
|
||
return func(r1 *restful.Request, r2 *restful.Response, fc *restful.FilterChain) {
|
||
sr := r1.SelectedRoute()
|
||
md := NewMetaData(sr.Metadata())
|
||
|
||
// 开关打开,则开启审计
|
||
if md.GetBool(event.META_AUDIT_KEY) {
|
||
|
||
// 获取当前是否需要审计
|
||
e := event.NewEvent()
|
||
|
||
// 用户信息
|
||
tk := token.GetTokenFromCtx(r1.Request.Context())
|
||
if tk != nil {
|
||
e.Who = tk.UserName
|
||
e.Extras["namespace"] = tk.NamespaceName
|
||
}
|
||
|
||
// ioc 里面获取当前应用的名称
|
||
e.Service = application.Get().AppName
|
||
e.ResourceType = md.GetString(endpoint.META_RESOURCE_KEY)
|
||
e.Action = md.GetString(endpoint.META_ACTION_KEY)
|
||
|
||
// {id} /:id
|
||
e.ResourceId = r1.PathParameter("id")
|
||
e.UserAgent = r1.Request.UserAgent()
|
||
e.Extras["method"] = sr.Method()
|
||
e.Extras["path"] = sr.Path()
|
||
e.Extras["operation"] = sr.Operation()
|
||
|
||
// 补充处理后的数据
|
||
e.StatusCode = r2.StatusCode()
|
||
// 发送给topic, 使用这个中间件的使用者,需要配置kafka
|
||
err := a.wirter.WriteMessages(context.Background(), e.ToKafkaMessage())
|
||
if err != nil {
|
||
a.log.Error().Msgf("send message error, %s", err)
|
||
} else {
|
||
a.log.Debug().Msgf("send audit event ok, who: %s, resource: %s, action: %s", e.Who, e.ResourceType, e.Action)
|
||
}
|
||
}
|
||
|
||
// 路有给后续逻辑
|
||
fc.ProcessFilter(r1, r2)
|
||
}
|
||
}
|
||
|
||
func NewMetaData(data map[string]any) *MetaData {
|
||
return &MetaData{
|
||
data: data,
|
||
}
|
||
}
|
||
|
||
type MetaData struct {
|
||
data map[string]any
|
||
}
|
||
|
||
func (m *MetaData) GetString(key string) string {
|
||
if v, ok := m.data[key]; ok {
|
||
return v.(string)
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func (m *MetaData) GetBool(key string) bool {
|
||
if v, ok := m.data[key]; ok {
|
||
return v.(bool)
|
||
}
|
||
return false
|
||
}
|