[#1184] node: Add audit package
Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
parent
7b8937ec35
commit
ac1f014747
5 changed files with 208 additions and 1 deletions
2
go.mod
2
go.mod
|
@ -6,6 +6,7 @@ require (
|
|||
code.gitea.io/sdk/gitea v0.17.1
|
||||
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240530152826-2f6d3209e1d3
|
||||
git.frostfs.info/TrueCloudLab/frostfs-contract v0.19.3-0.20240409111539-e7a05a49ff45
|
||||
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0
|
||||
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65
|
||||
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de
|
||||
git.frostfs.info/TrueCloudLab/hrw v1.2.1
|
||||
|
@ -54,7 +55,6 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 // indirect
|
||||
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
|
|
7
internal/audit/consts.go
Normal file
7
internal/audit/consts.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
package audit
|
||||
|
||||
const (
|
||||
InvalidValue = "invalid_value"
|
||||
NotDefined = "not_defined"
|
||||
Empty = "empty"
|
||||
)
|
41
internal/audit/request.go
Normal file
41
internal/audit/request.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
package audit
|
||||
|
||||
import (
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||
crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type Request interface {
|
||||
GetVerificationHeader() *session.RequestVerificationHeader
|
||||
}
|
||||
|
||||
type Target interface {
|
||||
String() string
|
||||
}
|
||||
|
||||
func LogRequest(log *logger.Logger, operation string, req Request, target Target, status bool) {
|
||||
LogRequestWithKey(log, operation, req.GetVerificationHeader().GetBodySignature().GetKey(), target, status)
|
||||
}
|
||||
|
||||
func LogRequestWithKey(log *logger.Logger, operation string, key []byte, target Target, status bool) {
|
||||
object, subject := NotDefined, NotDefined
|
||||
|
||||
publicKey := crypto.UnmarshalPublicKey(key)
|
||||
if publicKey != nil {
|
||||
subject = ((*keys.PublicKey)(publicKey)).StringCompressed()
|
||||
}
|
||||
|
||||
if target != nil {
|
||||
object = target.String()
|
||||
}
|
||||
|
||||
log.Info(logs.AuditEventLogRecord,
|
||||
zap.String("operation", operation),
|
||||
zap.String("object", object),
|
||||
zap.String("subject", subject),
|
||||
zap.Bool("success", status))
|
||||
}
|
158
internal/audit/target.go
Normal file
158
internal/audit/target.go
Normal file
|
@ -0,0 +1,158 @@
|
|||
package audit
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"github.com/mr-tron/base58"
|
||||
)
|
||||
|
||||
type ModelType[T any] interface {
|
||||
ReadFromV2(m T) error
|
||||
String() string
|
||||
}
|
||||
|
||||
func TargetFromRef[T any](ref *T, model ModelType[T]) Target {
|
||||
if ref == nil {
|
||||
return stringTarget{s: NotDefined}
|
||||
}
|
||||
if err := model.ReadFromV2(*ref); err != nil {
|
||||
return stringTarget{s: InvalidValue}
|
||||
}
|
||||
return stringTarget{s: model.String()}
|
||||
}
|
||||
|
||||
func TargetFromRefs[T any](refs []*T, model ModelType[T]) Target {
|
||||
if len(refs) == 0 {
|
||||
return stringTarget{s: NotDefined}
|
||||
}
|
||||
sb := &strings.Builder{}
|
||||
for idx, ref := range refs {
|
||||
if idx > 0 {
|
||||
sb.WriteString(";")
|
||||
}
|
||||
if ref == nil {
|
||||
sb.WriteString(Empty)
|
||||
continue
|
||||
}
|
||||
if err := model.ReadFromV2(*ref); err != nil {
|
||||
sb.WriteString(InvalidValue)
|
||||
} else {
|
||||
sb.WriteString(model.String())
|
||||
}
|
||||
}
|
||||
return sb
|
||||
}
|
||||
|
||||
type stringTarget struct {
|
||||
s string
|
||||
}
|
||||
|
||||
func (t stringTarget) String() string {
|
||||
return t.s
|
||||
}
|
||||
|
||||
func TargetFromString(s string) Target {
|
||||
if len(s) == 0 {
|
||||
s = Empty
|
||||
}
|
||||
return stringTarget{s: s}
|
||||
}
|
||||
|
||||
func TargetFromStringSlice(s []string) Target {
|
||||
if len(s) == 0 {
|
||||
return stringTarget{s: NotDefined}
|
||||
}
|
||||
sb := &strings.Builder{}
|
||||
for i, v := range s {
|
||||
if i > 0 {
|
||||
sb.WriteString(";")
|
||||
}
|
||||
if len(v) == 0 {
|
||||
sb.WriteString(Empty)
|
||||
} else {
|
||||
sb.WriteString(v)
|
||||
}
|
||||
}
|
||||
return sb
|
||||
}
|
||||
|
||||
func TargetFromChainID(chainTargetType, chainTargetName string, chainID []byte) Target {
|
||||
if len(chainTargetType) == 0 && len(chainTargetName) == 0 && len(chainID) == 0 {
|
||||
return stringTarget{s: NotDefined}
|
||||
}
|
||||
t, n, c := Empty, Empty, Empty
|
||||
if len(chainTargetType) > 0 {
|
||||
t = chainTargetType
|
||||
}
|
||||
if len(chainTargetName) > 0 {
|
||||
n = chainTargetName
|
||||
}
|
||||
if len(chainID) > 0 {
|
||||
c = string(chainID)
|
||||
}
|
||||
return stringTarget{s: t + ":" + n + ":" + c}
|
||||
}
|
||||
|
||||
func TargetFromShardIDs(v [][]byte) Target {
|
||||
if len(v) == 0 {
|
||||
return stringTarget{s: NotDefined}
|
||||
}
|
||||
sb := &strings.Builder{}
|
||||
for i, s := range v {
|
||||
if i > 0 {
|
||||
sb.WriteString(";")
|
||||
}
|
||||
if len(s) == 0 {
|
||||
sb.WriteString(Empty)
|
||||
} else {
|
||||
sb.WriteString(base58.Encode(s))
|
||||
}
|
||||
}
|
||||
return sb
|
||||
}
|
||||
|
||||
func TargetFromTreeID(containerID []byte, treeID string) Target {
|
||||
if len(containerID) == 0 && len(treeID) == 0 {
|
||||
return stringTarget{s: NotDefined}
|
||||
}
|
||||
c, t := Empty, Empty
|
||||
if len(containerID) > 0 {
|
||||
var cnr cid.ID
|
||||
if err := cnr.Decode(containerID); err != nil {
|
||||
c = InvalidValue
|
||||
} else {
|
||||
c = cnr.EncodeToString()
|
||||
}
|
||||
}
|
||||
if len(treeID) > 0 {
|
||||
t = treeID
|
||||
}
|
||||
return stringTarget{s: c + ":" + t}
|
||||
}
|
||||
|
||||
func TargetFromContainerIDObjectID(containerID *refs.ContainerID, objectID *refs.ObjectID) Target {
|
||||
if containerID == nil && objectID == nil {
|
||||
return stringTarget{s: NotDefined}
|
||||
}
|
||||
c, o := Empty, Empty
|
||||
if containerID != nil {
|
||||
var cnr cid.ID
|
||||
if err := cnr.ReadFromV2(*containerID); err != nil {
|
||||
c = InvalidValue
|
||||
} else {
|
||||
c = cnr.EncodeToString()
|
||||
}
|
||||
}
|
||||
if objectID != nil {
|
||||
var obj oid.ID
|
||||
if err := obj.ReadFromV2(*objectID); err != nil {
|
||||
o = InvalidValue
|
||||
} else {
|
||||
o = obj.EncodeToString()
|
||||
}
|
||||
}
|
||||
return stringTarget{s: c + "/" + o}
|
||||
}
|
|
@ -539,4 +539,5 @@ const (
|
|||
PolicerFailedToRestoreObject = "failed to restore EC object"
|
||||
PolicerCouldNotGetChunk = "could not get EC chunk"
|
||||
PolicerCouldNotGetChunks = "could not get EC chunks"
|
||||
AuditEventLogRecord = "audit event log record"
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue