Audit grpc requests #1184
34 changed files with 1368 additions and 43 deletions
|
@ -35,6 +35,7 @@ func reloadConfig() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cmode.Store(cfg.GetBool("node.kludge_compatibility_mode"))
|
cmode.Store(cfg.GetBool("node.kludge_compatibility_mode"))
|
||||||
|
audit.Store(cfg.GetBool("audit.enabled"))
|
||||||
err = logPrm.SetLevelString(cfg.GetString("logger.level"))
|
err = logPrm.SetLevelString(cfg.GetString("logger.level"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -45,6 +45,8 @@ func defaultConfiguration(cfg *viper.Viper) {
|
||||||
cfg.SetDefault("governance.disable", false)
|
cfg.SetDefault("governance.disable", false)
|
||||||
|
|
||||||
cfg.SetDefault("node.kludge_compatibility_mode", false)
|
cfg.SetDefault("node.kludge_compatibility_mode", false)
|
||||||
|
|
||||||
|
cfg.SetDefault("audit.enabled", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setControlDefaults(cfg *viper.Viper) {
|
func setControlDefaults(cfg *viper.Viper) {
|
||||||
|
|
|
@ -39,6 +39,7 @@ var (
|
||||||
configFile *string
|
configFile *string
|
||||||
configDir *string
|
configDir *string
|
||||||
cmode = &atomic.Bool{}
|
cmode = &atomic.Bool{}
|
||||||
|
audit = &atomic.Bool{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func exitErr(err error) {
|
func exitErr(err error) {
|
||||||
|
@ -87,8 +88,9 @@ func main() {
|
||||||
|
|
||||||
metricsCmp = newMetricsComponent()
|
metricsCmp = newMetricsComponent()
|
||||||
metricsCmp.init()
|
metricsCmp.init()
|
||||||
|
audit.Store(cfg.GetBool("audit.enabled"))
|
||||||
|
|
||||||
innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics, cmode)
|
innerRing, err = innerring.New(ctx, log, cfg, intErr, metrics, cmode, audit)
|
||||||
exitErr(err)
|
exitErr(err)
|
||||||
|
|
||||||
pprofCmp.start()
|
pprofCmp.start()
|
||||||
|
|
|
@ -20,15 +20,16 @@ func initAccountingService(ctx context.Context, c *cfg) {
|
||||||
balanceMorphWrapper, err := balance.NewFromMorph(c.cfgMorph.client, c.cfgAccounting.scriptHash, 0)
|
balanceMorphWrapper, err := balance.NewFromMorph(c.cfgMorph.client, c.cfgAccounting.scriptHash, 0)
|
||||||
fatalOnErr(err)
|
fatalOnErr(err)
|
||||||
|
|
||||||
server := accountingTransportGRPC.New(
|
service := accountingService.NewSignService(
|
||||||
accountingService.NewSignService(
|
|
||||||
&c.key.PrivateKey,
|
&c.key.PrivateKey,
|
||||||
accountingService.NewExecutionService(
|
accountingService.NewExecutionService(
|
||||||
accounting.NewExecutor(balanceMorphWrapper),
|
accounting.NewExecutor(balanceMorphWrapper),
|
||||||
c.respSvc,
|
c.respSvc,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
service = accountingService.NewAuditService(service, c.log, c.audit)
|
||||||
|
|
||||||
|
server := accountingTransportGRPC.New(service)
|
||||||
|
|
||||||
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
|
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
|
||||||
accountingGRPC.RegisterAccountingServiceServer(s, server)
|
accountingGRPC.RegisterAccountingServiceServer(s, server)
|
||||||
|
|
|
@ -21,7 +21,8 @@ func initAPEManagerService(c *cfg) {
|
||||||
execsvc := apemanager.New(c.cfgObject.cnrSource, contractStorage,
|
execsvc := apemanager.New(c.cfgObject.cnrSource, contractStorage,
|
||||||
apemanager.WithLogger(c.log))
|
apemanager.WithLogger(c.log))
|
||||||
sigsvc := apemanager.NewSignService(&c.key.PrivateKey, execsvc)
|
sigsvc := apemanager.NewSignService(&c.key.PrivateKey, execsvc)
|
||||||
server := apemanager_transport.New(sigsvc)
|
auditSvc := apemanager.NewAuditService(sigsvc, c.log, c.audit)
|
||||||
|
server := apemanager_transport.New(auditSvc)
|
||||||
|
|
||||||
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
|
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
|
||||||
apemanager_grpc.RegisterAPEManagerServiceServer(s, server)
|
apemanager_grpc.RegisterAPEManagerServiceServer(s, server)
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
netmapV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
netmapV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
||||||
apiclientconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/apiclient"
|
apiclientconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/apiclient"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/audit"
|
||||||
contractsconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/contracts"
|
contractsconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/contracts"
|
||||||
engineconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine"
|
engineconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine"
|
||||||
shardconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard"
|
shardconfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/engine/shard"
|
||||||
|
@ -375,6 +376,7 @@ type internals struct {
|
||||||
healthStatus *atomic.Int32
|
healthStatus *atomic.Int32
|
||||||
// is node under maintenance
|
// is node under maintenance
|
||||||
isMaintenance atomic.Bool
|
isMaintenance atomic.Bool
|
||||||
|
audit *atomic.Bool
|
||||||
|
|
||||||
sdNotify bool
|
sdNotify bool
|
||||||
}
|
}
|
||||||
|
@ -722,6 +724,9 @@ func initInternals(appCfg *config.Config, log *logger.Logger) internals {
|
||||||
var healthStatus atomic.Int32
|
var healthStatus atomic.Int32
|
||||||
healthStatus.Store(int32(control.HealthStatus_HEALTH_STATUS_UNDEFINED))
|
healthStatus.Store(int32(control.HealthStatus_HEALTH_STATUS_UNDEFINED))
|
||||||
|
|
||||||
|
var auditRequests atomic.Bool
|
||||||
|
auditRequests.Store(audit.Enabled(appCfg))
|
||||||
|
|
||||||
return internals{
|
return internals{
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
appCfg: appCfg,
|
appCfg: appCfg,
|
||||||
|
@ -730,6 +735,7 @@ func initInternals(appCfg *config.Config, log *logger.Logger) internals {
|
||||||
apiVersion: version.Current(),
|
apiVersion: version.Current(),
|
||||||
healthStatus: &healthStatus,
|
healthStatus: &healthStatus,
|
||||||
sdNotify: initSdNotify(appCfg),
|
sdNotify: initSdNotify(appCfg),
|
||||||
|
audit: &auditRequests,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1278,6 +1284,10 @@ func (c *cfg) reloadConfig(ctx context.Context) {
|
||||||
setRuntimeParameters(c)
|
setRuntimeParameters(c)
|
||||||
return nil
|
return nil
|
||||||
}})
|
}})
|
||||||
|
components = append(components, dCmp{"audit", func() error {
|
||||||
|
c.audit.Store(audit.Enabled(c.appCfg))
|
||||||
|
return nil
|
||||||
|
}})
|
||||||
components = append(components, dCmp{"pools", c.reloadPools})
|
components = append(components, dCmp{"pools", c.reloadPools})
|
||||||
components = append(components, dCmp{"tracing", func() error {
|
components = append(components, dCmp{"tracing", func() error {
|
||||||
updated, err := tracing.Setup(ctx, *tracingconfig.ToTracingConfig(c.appCfg))
|
updated, err := tracing.Setup(ctx, *tracingconfig.ToTracingConfig(c.appCfg))
|
||||||
|
|
12
cmd/frostfs-node/config/audit/config.go
Normal file
12
cmd/frostfs-node/config/audit/config.go
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package audit
|
||||||
|
|
||||||
|
import "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
||||||
|
|
||||||
|
const (
|
||||||
|
subsection = "audit"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Enabled returns the value of "enabled" config parameter from "audit" section.
|
||||||
|
func Enabled(c *config.Config) bool {
|
||||||
|
return config.BoolSafe(c.Sub(subsection), "enabled")
|
||||||
|
}
|
28
cmd/frostfs-node/config/audit/config_test.go
Normal file
28
cmd/frostfs-node/config/audit/config_test.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
package audit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config"
|
||||||
|
configtest "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-node/config/test"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAuditSection(t *testing.T) {
|
||||||
|
t.Run("defaults", func(t *testing.T) {
|
||||||
|
empty := configtest.EmptyConfig()
|
||||||
|
require.Equal(t, false, Enabled(empty))
|
||||||
|
})
|
||||||
|
|
||||||
|
const path = "../../../../config/example/node"
|
||||||
|
|
||||||
|
fileConfigTest := func(c *config.Config) {
|
||||||
|
require.Equal(t, true, Enabled(c))
|
||||||
|
}
|
||||||
|
|
||||||
|
configtest.ForEachFileType(path, fileConfigTest)
|
||||||
|
|
||||||
|
t.Run("ENV", func(t *testing.T) {
|
||||||
|
configtest.ForEnvFileType(t, path, fileConfigTest)
|
||||||
|
})
|
||||||
|
}
|
|
@ -46,15 +46,15 @@ func initContainerService(_ context.Context, c *cfg) {
|
||||||
|
|
||||||
c.shared.frostfsidClient = frostfsIDSubjectProvider
|
c.shared.frostfsidClient = frostfsIDSubjectProvider
|
||||||
|
|
||||||
server := containerTransportGRPC.New(
|
service := containerService.NewSignService(
|
||||||
containerService.NewSignService(
|
|
||||||
&c.key.PrivateKey,
|
&c.key.PrivateKey,
|
||||||
containerService.NewAPEServer(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine, cnrRdr,
|
containerService.NewAPEServer(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine, cnrRdr,
|
||||||
newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, c.shared.frostfsidClient,
|
newCachedIRFetcher(createInnerRingFetcher(c)), c.netMapSource, c.shared.frostfsidClient,
|
||||||
containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc),
|
containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt), c.respSvc),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
service = containerService.NewAuditService(service, c.log, c.audit)
|
||||||
|
server := containerTransportGRPC.New(service)
|
||||||
|
|
||||||
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
|
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
|
||||||
containerGRPC.RegisterContainerServiceServer(s, server)
|
containerGRPC.RegisterContainerServiceServer(s, server)
|
||||||
|
|
|
@ -30,8 +30,8 @@ func initControlService(c *cfg) {
|
||||||
for i := range pubs {
|
for i := range pubs {
|
||||||
rawPubs = append(rawPubs, pubs[i].Bytes())
|
rawPubs = append(rawPubs, pubs[i].Bytes())
|
||||||
}
|
}
|
||||||
|
var ctlSvc control.ControlServiceServer
|
||||||
ctlSvc := controlSvc.New(
|
ctlSvc = controlSvc.New(
|
||||||
controlSvc.WithKey(&c.key.PrivateKey),
|
controlSvc.WithKey(&c.key.PrivateKey),
|
||||||
controlSvc.WithAuthorizedKeys(rawPubs),
|
controlSvc.WithAuthorizedKeys(rawPubs),
|
||||||
controlSvc.WithHealthChecker(c),
|
controlSvc.WithHealthChecker(c),
|
||||||
|
@ -43,6 +43,7 @@ func initControlService(c *cfg) {
|
||||||
controlSvc.WithTreeService(c.treeService),
|
controlSvc.WithTreeService(c.treeService),
|
||||||
controlSvc.WithLocalOverrideStorage(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine),
|
controlSvc.WithLocalOverrideStorage(c.cfgObject.cfgAccessPolicyEngine.accessPolicyEngine),
|
||||||
)
|
)
|
||||||
|
ctlSvc = controlSvc.NewAuditService(ctlSvc, c.log, c.audit)
|
||||||
|
|
||||||
lis, err := net.Listen("tcp", endpoint)
|
lis, err := net.Listen("tcp", endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -147,8 +147,7 @@ func initNetmapService(ctx context.Context, c *cfg) {
|
||||||
|
|
||||||
initNetmapState(c)
|
initNetmapState(c)
|
||||||
|
|
||||||
server := netmapTransportGRPC.New(
|
svc := netmapService.NewSignService(
|
||||||
netmapService.NewSignService(
|
|
||||||
&c.key.PrivateKey,
|
&c.key.PrivateKey,
|
||||||
netmapService.NewExecutionService(
|
netmapService.NewExecutionService(
|
||||||
c,
|
c,
|
||||||
|
@ -161,8 +160,9 @@ func initNetmapService(ctx context.Context, c *cfg) {
|
||||||
},
|
},
|
||||||
c.respSvc,
|
c.respSvc,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
svc = netmapService.NewAuditService(svc, c.log, c.audit)
|
||||||
|
server := netmapTransportGRPC.New(svc)
|
||||||
|
|
||||||
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
|
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
|
||||||
netmapGRPC.RegisterNetmapServiceServer(s, server)
|
netmapGRPC.RegisterNetmapServiceServer(s, server)
|
||||||
|
|
|
@ -182,7 +182,7 @@ func initObjectService(c *cfg) {
|
||||||
sDeleteV2 := createDeleteServiceV2(sDelete)
|
sDeleteV2 := createDeleteServiceV2(sDelete)
|
||||||
|
|
||||||
// build service pipeline
|
// build service pipeline
|
||||||
// grpc | <metrics> | signature | response | acl | ape | split
|
// grpc | audit | <metrics> | signature | response | acl | ape | split
|
||||||
|
|
||||||
splitSvc := createSplitService(c, sPutV2, sGetV2, sSearchV2, sDeleteV2)
|
splitSvc := createSplitService(c, sPutV2, sGetV2, sSearchV2, sDeleteV2)
|
||||||
|
|
||||||
|
@ -205,7 +205,8 @@ func initObjectService(c *cfg) {
|
||||||
|
|
||||||
c.shared.metricsSvc = objectService.NewMetricCollector(
|
c.shared.metricsSvc = objectService.NewMetricCollector(
|
||||||
signSvc, c.metricsCollector.ObjectService(), metricsconfig.Enabled(c.appCfg))
|
signSvc, c.metricsCollector.ObjectService(), metricsconfig.Enabled(c.appCfg))
|
||||||
server := objectTransportGRPC.New(c.shared.metricsSvc)
|
auditSvc := objectService.NewAuditService(c.shared.metricsSvc, c.log, c.audit)
|
||||||
|
server := objectTransportGRPC.New(auditSvc)
|
||||||
|
|
||||||
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
|
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
|
||||||
objectGRPC.RegisterObjectServiceServer(s, server)
|
objectGRPC.RegisterObjectServiceServer(s, server)
|
||||||
|
|
|
@ -52,12 +52,13 @@ func initSessionService(c *cfg) {
|
||||||
c.privateTokenStore.RemoveOld(ev.(netmap.NewEpoch).EpochNumber())
|
c.privateTokenStore.RemoveOld(ev.(netmap.NewEpoch).EpochNumber())
|
||||||
})
|
})
|
||||||
|
|
||||||
server := sessionTransportGRPC.New(
|
svc := sessionSvc.NewAuditService(
|
||||||
sessionSvc.NewSignService(
|
sessionSvc.NewSignService(
|
||||||
&c.key.PrivateKey,
|
&c.key.PrivateKey,
|
||||||
sessionSvc.NewExecutionService(c.privateTokenStore, c.respSvc, c.log),
|
sessionSvc.NewExecutionService(c.privateTokenStore, c.respSvc, c.log),
|
||||||
),
|
),
|
||||||
)
|
c.log, c.audit)
|
||||||
|
server := sessionTransportGRPC.New(svc)
|
||||||
|
|
||||||
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
|
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
|
||||||
sessionGRPC.RegisterSessionServiceServer(s, server)
|
sessionGRPC.RegisterSessionServiceServer(s, server)
|
||||||
|
|
|
@ -70,7 +70,7 @@ func initTreeService(c *cfg) {
|
||||||
)
|
)
|
||||||
|
|
||||||
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
|
c.cfgGRPC.performAndSave(func(_ string, _ net.Listener, s *grpc.Server) {
|
||||||
tree.RegisterTreeServiceServer(s, c.treeService)
|
tree.RegisterTreeServiceServer(s, tree.NewAuditService(c.treeService, c.log, c.audit))
|
||||||
})
|
})
|
||||||
|
|
||||||
c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) {
|
c.workers = append(c.workers, newWorkerFromFunc(func(ctx context.Context) {
|
||||||
|
|
|
@ -202,3 +202,6 @@ FROSTFS_TRACING_ENDPOINT="localhost"
|
||||||
FROSTFS_TRACING_EXPORTER="otlp_grpc"
|
FROSTFS_TRACING_EXPORTER="otlp_grpc"
|
||||||
|
|
||||||
FROSTFS_RUNTIME_SOFT_MEMORY_LIMIT=1073741824
|
FROSTFS_RUNTIME_SOFT_MEMORY_LIMIT=1073741824
|
||||||
|
|
||||||
|
# AUDIT section
|
||||||
|
FROSTFS_AUDIT_ENABLED=true
|
||||||
|
|
|
@ -260,5 +260,8 @@
|
||||||
},
|
},
|
||||||
"runtime": {
|
"runtime": {
|
||||||
"soft_memory_limit": 1073741824
|
"soft_memory_limit": 1073741824
|
||||||
|
},
|
||||||
|
"audit": {
|
||||||
|
"enabled": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,3 +234,6 @@ tracing:
|
||||||
|
|
||||||
runtime:
|
runtime:
|
||||||
soft_memory_limit: 1gb
|
soft_memory_limit: 1gb
|
||||||
|
|
||||||
|
audit:
|
||||||
|
enabled: true
|
||||||
|
|
|
@ -25,6 +25,7 @@ There are some custom types used for brevity:
|
||||||
| `replicator` | [Replicator service configuration](#replicator-section) |
|
| `replicator` | [Replicator service configuration](#replicator-section) |
|
||||||
| `storage` | [Storage engine configuration](#storage-section) |
|
| `storage` | [Storage engine configuration](#storage-section) |
|
||||||
| `runtime` | [Runtime configuration](#runtime-section) |
|
| `runtime` | [Runtime configuration](#runtime-section) |
|
||||||
|
| `audit` | [Audit configuration](#audit-section) |
|
||||||
|
|
||||||
|
|
||||||
# `control` section
|
# `control` section
|
||||||
|
@ -428,3 +429,15 @@ runtime:
|
||||||
| Parameter | Type | Default value | Description |
|
| Parameter | Type | Default value | Description |
|
||||||
|---------------------|--------|---------------|--------------------------------------------------------------------------|
|
|---------------------|--------|---------------|--------------------------------------------------------------------------|
|
||||||
| `soft_memory_limit` | `size` | 0 | Soft memory limit for the runtime. Zero or no value stands for no limit. If `GOMEMLIMIT` environment variable is set, the value from the configuration file will be ignored. |
|
| `soft_memory_limit` | `size` | 0 | Soft memory limit for the runtime. Zero or no value stands for no limit. If `GOMEMLIMIT` environment variable is set, the value from the configuration file will be ignored. |
|
||||||
|
|
||||||
|
# `audit` section
|
||||||
|
Contains audit parameters.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
audit:
|
||||||
|
enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
| Parameter | Type | Default value | Description |
|
||||||
|
|---------------------|--------|---------------|---------------------------------------------------|
|
||||||
|
| `soft_memory_limit` | `bool` | false | If `true` then audit event logs will be recorded. |
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -6,6 +6,7 @@ require (
|
||||||
code.gitea.io/sdk/gitea v0.17.1
|
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-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-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-observability v0.0.0-20231101111734-b3ad3335ff65
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de
|
git.frostfs.info/TrueCloudLab/frostfs-sdk-go v0.0.0-20240617140730-1a5886e776de
|
||||||
git.frostfs.info/TrueCloudLab/hrw v1.2.1
|
git.frostfs.info/TrueCloudLab/hrw v1.2.1
|
||||||
|
@ -54,7 +55,6 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.frostfs.info/TrueCloudLab/frostfs-crypto v0.6.0 // indirect
|
|
||||||
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect
|
git.frostfs.info/TrueCloudLab/rfc6979 v0.4.0 // indirect
|
||||||
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // 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"
|
PolicerFailedToRestoreObject = "failed to restore EC object"
|
||||||
PolicerCouldNotGetChunk = "could not get EC chunk"
|
PolicerCouldNotGetChunk = "could not get EC chunk"
|
||||||
PolicerCouldNotGetChunks = "could not get EC chunks"
|
PolicerCouldNotGetChunks = "could not get EC chunks"
|
||||||
|
AuditEventLogRecord = "audit event log record"
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring/processors/alphabet"
|
||||||
|
@ -26,6 +27,7 @@ import (
|
||||||
control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir"
|
control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir"
|
||||||
controlsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server"
|
controlsrv "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir/server"
|
||||||
utilConfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/config"
|
utilConfig "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/config"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
@ -310,7 +312,7 @@ func (s *Server) initFrostFSMainnetProcessor(cfg *viper.Viper) error {
|
||||||
return bindMainnetProcessor(frostfsProcessor, s)
|
return bindMainnetProcessor(frostfsProcessor, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) initGRPCServer(cfg *viper.Viper) error {
|
func (s *Server) initGRPCServer(cfg *viper.Viper, log *logger.Logger, audit *atomic.Bool) error {
|
||||||
controlSvcEndpoint := cfg.GetString("control.grpc.endpoint")
|
controlSvcEndpoint := cfg.GetString("control.grpc.endpoint")
|
||||||
if controlSvcEndpoint == "" {
|
if controlSvcEndpoint == "" {
|
||||||
s.log.Info(logs.InnerringNoControlServerEndpointSpecified)
|
s.log.Info(logs.InnerringNoControlServerEndpointSpecified)
|
||||||
|
@ -337,9 +339,9 @@ func (s *Server) initGRPCServer(cfg *viper.Viper) error {
|
||||||
p.SetPrivateKey(*s.key)
|
p.SetPrivateKey(*s.key)
|
||||||
p.SetHealthChecker(s)
|
p.SetHealthChecker(s)
|
||||||
|
|
||||||
controlSvc := controlsrv.New(p, s.netmapClient, s.containerClient,
|
controlSvc := controlsrv.NewAuditService(controlsrv.New(p, s.netmapClient, s.containerClient,
|
||||||
controlsrv.WithAllowedKeys(authKeys),
|
controlsrv.WithAllowedKeys(authKeys),
|
||||||
)
|
), log, audit)
|
||||||
|
|
||||||
grpcControlSrv := grpc.NewServer()
|
grpcControlSrv := grpc.NewServer()
|
||||||
control.RegisterControlServiceServer(grpcControlSrv, controlSvc)
|
control.RegisterControlServiceServer(grpcControlSrv, controlSvc)
|
||||||
|
|
|
@ -331,7 +331,7 @@ func (s *Server) registerStarter(f func() error) {
|
||||||
|
|
||||||
// New creates instance of inner ring sever structure.
|
// New creates instance of inner ring sever structure.
|
||||||
func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan<- error,
|
func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan<- error,
|
||||||
metrics *metrics.InnerRingServiceMetrics, cmode *atomic.Bool,
|
metrics *metrics.InnerRingServiceMetrics, cmode *atomic.Bool, audit *atomic.Bool,
|
||||||
) (*Server, error) {
|
) (*Server, error) {
|
||||||
var err error
|
var err error
|
||||||
server := &Server{
|
server := &Server{
|
||||||
|
@ -403,7 +403,7 @@ func New(ctx context.Context, log *logger.Logger, cfg *viper.Viper, errChan chan
|
||||||
|
|
||||||
server.initTimers(cfg, morphClients)
|
server.initTimers(cfg, morphClients)
|
||||||
|
|
||||||
err = server.initGRPCServer(cfg)
|
err = server.initGRPCServer(cfg, log, audit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
42
pkg/services/accounting/audit.go
Normal file
42
pkg/services/accounting/audit.go
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
package accounting
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting"
|
||||||
|
acc_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/accounting/grpc"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ Server = (*auditService)(nil)
|
||||||
|
|
||||||
|
type auditService struct {
|
||||||
|
next Server
|
||||||
|
log *logger.Logger
|
||||||
|
enabled *atomic.Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Server {
|
||||||
|
return &auditService{
|
||||||
|
next: next,
|
||||||
|
log: log,
|
||||||
|
enabled: enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Balance implements Server.
|
||||||
|
func (l *auditService) Balance(ctx context.Context, req *accounting.BalanceRequest) (*accounting.BalanceResponse, error) {
|
||||||
|
res, err := l.next.Balance(ctx, req)
|
||||||
|
|
||||||
|
if !l.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
audit.LogRequest(l.log, acc_grpc.AccountingService_Balance_FullMethodName, req,
|
||||||
|
audit.TargetFromRef(req.GetBody().GetOwnerID(), &user.ID{}), err == nil)
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
75
pkg/services/apemanager/audit.go
Normal file
75
pkg/services/apemanager/audit.go
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
package apemanager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
|
||||||
|
ape_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager/grpc"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ Server = (*auditService)(nil)
|
||||||
|
|
||||||
|
type auditService struct {
|
||||||
|
next Server
|
||||||
|
log *logger.Logger
|
||||||
|
enabled *atomic.Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Server {
|
||||||
|
return &auditService{
|
||||||
|
next: next,
|
||||||
|
log: log,
|
||||||
|
enabled: enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddChain implements Server.
|
||||||
|
func (a *auditService) AddChain(ctx context.Context, req *apemanager.AddChainRequest) (*apemanager.AddChainResponse, error) {
|
||||||
|
res, err := a.next.AddChain(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
audit.LogRequest(a.log, ape_grpc.APEManagerService_AddChain_FullMethodName, req,
|
||||||
|
audit.TargetFromChainID(req.GetBody().GetTarget().GetTargetType().String(),
|
||||||
|
req.GetBody().GetTarget().GetName(),
|
||||||
|
res.GetBody().GetChainID()),
|
||||||
|
err == nil)
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListChains implements Server.
|
||||||
|
func (a *auditService) ListChains(ctx context.Context, req *apemanager.ListChainsRequest) (*apemanager.ListChainsResponse, error) {
|
||||||
|
res, err := a.next.ListChains(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
audit.LogRequest(a.log, ape_grpc.APEManagerService_ListChains_FullMethodName, req,
|
||||||
|
audit.TargetFromChainID(req.GetBody().GetTarget().GetTargetType().String(),
|
||||||
|
req.GetBody().GetTarget().GetName(),
|
||||||
|
nil),
|
||||||
|
err == nil)
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveChain implements Server.
|
||||||
|
func (a *auditService) RemoveChain(ctx context.Context, req *apemanager.RemoveChainRequest) (*apemanager.RemoveChainResponse, error) {
|
||||||
|
res, err := a.next.RemoveChain(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
audit.LogRequest(a.log, ape_grpc.APEManagerService_RemoveChain_FullMethodName, req,
|
||||||
|
audit.TargetFromChainID(req.GetBody().GetTarget().GetTargetType().String(),
|
||||||
|
req.GetBody().GetTarget().GetName(),
|
||||||
|
req.GetBody().GetChainID()),
|
||||||
|
err == nil)
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
116
pkg/services/container/audit.go
Normal file
116
pkg/services/container/audit.go
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
package container
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||||
|
container_grpc "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container/grpc"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||||
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ Server = (*auditService)(nil)
|
||||||
|
|
||||||
|
type auditService struct {
|
||||||
|
next Server
|
||||||
|
log *logger.Logger
|
||||||
|
enabled *atomic.Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Server {
|
||||||
|
return &auditService{
|
||||||
|
next: next,
|
||||||
|
log: log,
|
||||||
|
enabled: enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnnounceUsedSpace implements Server.
|
||||||
|
func (a *auditService) AnnounceUsedSpace(ctx context.Context, req *container.AnnounceUsedSpaceRequest) (*container.AnnounceUsedSpaceResponse, error) {
|
||||||
|
res, err := a.next.AnnounceUsedSpace(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var ids []*refs.ContainerID
|
||||||
|
for _, v := range req.GetBody().GetAnnouncements() {
|
||||||
|
ids = append(ids, v.GetContainerID())
|
||||||
|
}
|
||||||
|
|
||||||
|
audit.LogRequest(a.log, container_grpc.ContainerService_AnnounceUsedSpace_FullMethodName, req,
|
||||||
|
audit.TargetFromRefs(ids, &cid.ID{}), err == nil)
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete implements Server.
|
||||||
|
func (a *auditService) Delete(ctx context.Context, req *container.DeleteRequest) (*container.DeleteResponse, error) {
|
||||||
|
res, err := a.next.Delete(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
audit.LogRequest(a.log, container_grpc.ContainerService_Delete_FullMethodName, req,
|
||||||
|
audit.TargetFromRef(req.GetBody().GetContainerID(), &cid.ID{}), err == nil)
|
||||||
|
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get implements Server.
|
||||||
|
func (a *auditService) Get(ctx context.Context, req *container.GetRequest) (*container.GetResponse, error) {
|
||||||
|
res, err := a.next.Get(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, container_grpc.ContainerService_Get_FullMethodName, req,
|
||||||
|
audit.TargetFromRef(req.GetBody().GetContainerID(), &cid.ID{}), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetExtendedACL implements Server.
|
||||||
|
func (a *auditService) GetExtendedACL(ctx context.Context, req *container.GetExtendedACLRequest) (*container.GetExtendedACLResponse, error) {
|
||||||
|
res, err := a.next.GetExtendedACL(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, container_grpc.ContainerService_GetExtendedACL_FullMethodName, req,
|
||||||
|
audit.TargetFromRef(req.GetBody().GetContainerID(), &cid.ID{}), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// List implements Server.
|
||||||
|
func (a *auditService) List(ctx context.Context, req *container.ListRequest) (*container.ListResponse, error) {
|
||||||
|
res, err := a.next.List(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, container_grpc.ContainerService_List_FullMethodName, req,
|
||||||
|
audit.TargetFromRef(req.GetBody().GetOwnerID(), &user.ID{}), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put implements Server.
|
||||||
|
func (a *auditService) Put(ctx context.Context, req *container.PutRequest) (*container.PutResponse, error) {
|
||||||
|
res, err := a.next.Put(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, container_grpc.ContainerService_Put_FullMethodName, req,
|
||||||
|
audit.TargetFromRef(res.GetBody().GetContainerID(), &cid.ID{}), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetExtendedACL implements Server.
|
||||||
|
func (a *auditService) SetExtendedACL(ctx context.Context, req *container.SetExtendedACLRequest) (*container.SetExtendedACLResponse, error) {
|
||||||
|
res, err := a.next.SetExtendedACL(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, container_grpc.ContainerService_SetExtendedACL_FullMethodName, req,
|
||||||
|
audit.TargetFromRef(req.GetBody().GetEACL().GetContainerID(), &cid.ID{}), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
108
pkg/services/control/ir/server/audit.go
Normal file
108
pkg/services/control/ir/server/audit.go
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
package control
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit"
|
||||||
|
control "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control/ir"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||||
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ control.ControlServiceServer = (*auditService)(nil)
|
||||||
|
|
||||||
|
type auditService struct {
|
||||||
|
next *Server
|
||||||
|
log *logger.Logger
|
||||||
|
enabled *atomic.Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuditService(next *Server, log *logger.Logger, enabled *atomic.Bool) control.ControlServiceServer {
|
||||||
|
return &auditService{
|
||||||
|
next: next,
|
||||||
|
log: log,
|
||||||
|
enabled: enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HealthCheck implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) HealthCheck(ctx context.Context, req *control.HealthCheckRequest) (*control.HealthCheckResponse, error) {
|
||||||
|
res, err := a.next.HealthCheck(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, control.ControlService_HealthCheck_FullMethodName, req.GetSignature().GetKey(), nil, err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveContainer implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) RemoveContainer(ctx context.Context, req *control.RemoveContainerRequest) (*control.RemoveContainerResponse, error) {
|
||||||
|
res, err := a.next.RemoveContainer(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sb := &strings.Builder{}
|
||||||
|
var withConatiner bool
|
||||||
|
if len(req.GetBody().GetContainerId()) > 0 {
|
||||||
|
withConatiner = true
|
||||||
|
sb.WriteString("containerID:")
|
||||||
|
var containerID cid.ID
|
||||||
|
if err := containerID.Decode(req.GetBody().GetContainerId()); err != nil {
|
||||||
|
sb.WriteString(audit.InvalidValue)
|
||||||
|
} else {
|
||||||
|
sb.WriteString(containerID.EncodeToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(req.GetBody().GetOwner()) > 0 {
|
||||||
|
if withConatiner {
|
||||||
|
sb.WriteString(";")
|
||||||
|
}
|
||||||
|
sb.WriteString("owner:")
|
||||||
|
|
||||||
|
var ownerID refs.OwnerID
|
||||||
|
if err := ownerID.Unmarshal(req.GetBody().GetOwner()); err != nil {
|
||||||
|
sb.WriteString(audit.InvalidValue)
|
||||||
|
} else {
|
||||||
|
var owner user.ID
|
||||||
|
if err := owner.ReadFromV2(ownerID); err != nil {
|
||||||
|
sb.WriteString(audit.InvalidValue)
|
||||||
|
} else {
|
||||||
|
sb.WriteString(owner.EncodeToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
audit.LogRequestWithKey(a.log, control.ControlService_RemoveContainer_FullMethodName, req.GetSignature().GetKey(), sb, err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveNode implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) RemoveNode(ctx context.Context, req *control.RemoveNodeRequest) (*control.RemoveNodeResponse, error) {
|
||||||
|
res, err := a.next.RemoveNode(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
audit.LogRequestWithKey(a.log, control.ControlService_RemoveNode_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromString(hex.EncodeToString(req.GetBody().GetKey())), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TickEpoch implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) TickEpoch(ctx context.Context, req *control.TickEpochRequest) (*control.TickEpochResponse, error) {
|
||||||
|
res, err := a.next.TickEpoch(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
audit.LogRequestWithKey(a.log, control.ControlService_TickEpoch_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
nil, err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
287
pkg/services/control/server/audit.go
Normal file
287
pkg/services/control/server/audit.go
Normal file
|
@ -0,0 +1,287 @@
|
||||||
|
package control
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit"
|
||||||
|
ctl "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||||
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ ctl.ControlServiceServer = (*auditService)(nil)
|
||||||
|
|
||||||
|
type auditService struct {
|
||||||
|
next ctl.ControlServiceServer
|
||||||
|
log *logger.Logger
|
||||||
|
enabled *atomic.Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuditService(next ctl.ControlServiceServer, log *logger.Logger, enabled *atomic.Bool) ctl.ControlServiceServer {
|
||||||
|
return &auditService{
|
||||||
|
next: next,
|
||||||
|
log: log,
|
||||||
|
enabled: enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddChainLocalOverride implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) AddChainLocalOverride(ctx context.Context, req *ctl.AddChainLocalOverrideRequest) (*ctl.AddChainLocalOverrideResponse, error) {
|
||||||
|
res, err := a.next.AddChainLocalOverride(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_AddChainLocalOverride_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromChainID(req.GetBody().GetTarget().GetType().String(),
|
||||||
|
req.GetBody().GetTarget().GetName(),
|
||||||
|
res.GetBody().GetChainId()),
|
||||||
|
err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DetachShards implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) DetachShards(ctx context.Context, req *ctl.DetachShardsRequest) (*ctl.DetachShardsResponse, error) {
|
||||||
|
res, err := a.next.DetachShards(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_DetachShards_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Doctor implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) Doctor(ctx context.Context, req *ctl.DoctorRequest) (*ctl.DoctorResponse, error) {
|
||||||
|
res, err := a.next.Doctor(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_Doctor_FullMethodName, req.GetSignature().GetKey(), nil, err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// DropObjects implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) DropObjects(ctx context.Context, req *ctl.DropObjectsRequest) (*ctl.DropObjectsResponse, error) {
|
||||||
|
res, err := a.next.DropObjects(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
var list []string
|
||||||
|
for _, v := range req.GetBody().GetAddressList() {
|
||||||
|
if len(v) == 0 {
|
||||||
|
list = append(list, audit.Empty)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var a oid.Address
|
||||||
|
if e := a.DecodeString(string(v)); e != nil {
|
||||||
|
list = append(list, audit.InvalidValue)
|
||||||
|
} else {
|
||||||
|
list = append(list, a.EncodeToString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_DropObjects_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromStringSlice(list), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EvacuateShard implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) EvacuateShard(ctx context.Context, req *ctl.EvacuateShardRequest) (*ctl.EvacuateShardResponse, error) {
|
||||||
|
res, err := a.next.EvacuateShard(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_EvacuateShard_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlushCache implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) FlushCache(ctx context.Context, req *ctl.FlushCacheRequest) (*ctl.FlushCacheResponse, error) {
|
||||||
|
res, err := a.next.FlushCache(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_FlushCache_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetChainLocalOverride implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) GetChainLocalOverride(ctx context.Context, req *ctl.GetChainLocalOverrideRequest) (*ctl.GetChainLocalOverrideResponse, error) {
|
||||||
|
res, err := a.next.GetChainLocalOverride(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_GetChainLocalOverride_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromChainID(
|
||||||
|
req.GetBody().GetTarget().GetType().String(),
|
||||||
|
req.GetBody().GetTarget().GetName(),
|
||||||
|
req.GetBody().GetChainId()),
|
||||||
|
err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetShardEvacuationStatus implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) GetShardEvacuationStatus(ctx context.Context, req *ctl.GetShardEvacuationStatusRequest) (*ctl.GetShardEvacuationStatusResponse, error) {
|
||||||
|
res, err := a.next.GetShardEvacuationStatus(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_GetShardEvacuationStatus_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
nil, err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// HealthCheck implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) HealthCheck(ctx context.Context, req *ctl.HealthCheckRequest) (*ctl.HealthCheckResponse, error) {
|
||||||
|
res, err := a.next.HealthCheck(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_HealthCheck_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
nil, err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListChainLocalOverrides implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) ListChainLocalOverrides(ctx context.Context, req *ctl.ListChainLocalOverridesRequest) (*ctl.ListChainLocalOverridesResponse, error) {
|
||||||
|
res, err := a.next.ListChainLocalOverrides(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_ListChainLocalOverrides_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromChainID(req.GetBody().GetTarget().GetType().String(),
|
||||||
|
req.GetBody().GetTarget().GetName(),
|
||||||
|
nil),
|
||||||
|
err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListShards implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) ListShards(ctx context.Context, req *ctl.ListShardsRequest) (*ctl.ListShardsResponse, error) {
|
||||||
|
res, err := a.next.ListShards(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_ListShards_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
nil, err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListTargetsLocalOverrides implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) ListTargetsLocalOverrides(ctx context.Context, req *ctl.ListTargetsLocalOverridesRequest) (*ctl.ListTargetsLocalOverridesResponse, error) {
|
||||||
|
res, err := a.next.ListTargetsLocalOverrides(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_ListTargetsLocalOverrides_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromString(req.GetBody().GetChainName()), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveChainLocalOverride implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) RemoveChainLocalOverride(ctx context.Context, req *ctl.RemoveChainLocalOverrideRequest) (*ctl.RemoveChainLocalOverrideResponse, error) {
|
||||||
|
res, err := a.next.RemoveChainLocalOverride(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_RemoveChainLocalOverride_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromChainID(req.GetBody().GetTarget().GetType().String(),
|
||||||
|
req.GetBody().GetTarget().GetName(),
|
||||||
|
req.GetBody().GetChainId()),
|
||||||
|
err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveChainLocalOverridesByTarget implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) RemoveChainLocalOverridesByTarget(ctx context.Context, req *ctl.RemoveChainLocalOverridesByTargetRequest) (*ctl.RemoveChainLocalOverridesByTargetResponse, error) {
|
||||||
|
res, err := a.next.RemoveChainLocalOverridesByTarget(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_RemoveChainLocalOverridesByTarget_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromChainID(req.GetBody().GetTarget().GetType().String(),
|
||||||
|
req.GetBody().GetTarget().GetName(),
|
||||||
|
nil),
|
||||||
|
err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetShardEvacuationStatus implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) ResetShardEvacuationStatus(ctx context.Context, req *ctl.ResetShardEvacuationStatusRequest) (*ctl.ResetShardEvacuationStatusResponse, error) {
|
||||||
|
res, err := a.next.ResetShardEvacuationStatus(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_ResetShardEvacuationStatus_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
nil, err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SealWriteCache implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) SealWriteCache(ctx context.Context, req *ctl.SealWriteCacheRequest) (*ctl.SealWriteCacheResponse, error) {
|
||||||
|
res, err := a.next.SealWriteCache(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_SealWriteCache_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNetmapStatus implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) SetNetmapStatus(ctx context.Context, req *ctl.SetNetmapStatusRequest) (*ctl.SetNetmapStatusResponse, error) {
|
||||||
|
res, err := a.next.SetNetmapStatus(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_SetNetmapStatus_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
nil, err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetShardMode implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) SetShardMode(ctx context.Context, req *ctl.SetShardModeRequest) (*ctl.SetShardModeResponse, error) {
|
||||||
|
res, err := a.next.SetShardMode(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_SetShardMode_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartShardEvacuation implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) StartShardEvacuation(ctx context.Context, req *ctl.StartShardEvacuationRequest) (*ctl.StartShardEvacuationResponse, error) {
|
||||||
|
res, err := a.next.StartShardEvacuation(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_StartShardEvacuation_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromShardIDs(req.GetBody().GetShard_ID()), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// StopShardEvacuation implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) StopShardEvacuation(ctx context.Context, req *ctl.StopShardEvacuationRequest) (*ctl.StopShardEvacuationResponse, error) {
|
||||||
|
res, err := a.next.StopShardEvacuation(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_StopShardEvacuation_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
nil, err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SynchronizeTree implements control.ControlServiceServer.
|
||||||
|
func (a *auditService) SynchronizeTree(ctx context.Context, req *ctl.SynchronizeTreeRequest) (*ctl.SynchronizeTreeResponse, error) {
|
||||||
|
res, err := a.next.SynchronizeTree(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, ctl.ControlService_SynchronizeTree_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
60
pkg/services/netmap/audit.go
Normal file
60
pkg/services/netmap/audit.go
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
package netmap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap"
|
||||||
|
netmapGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/netmap/grpc"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ Server = (*auditService)(nil)
|
||||||
|
|
||||||
|
type auditService struct {
|
||||||
|
next Server
|
||||||
|
log *logger.Logger
|
||||||
|
enabled *atomic.Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Server {
|
||||||
|
return &auditService{
|
||||||
|
next: next,
|
||||||
|
log: log,
|
||||||
|
enabled: enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalNodeInfo implements Server.
|
||||||
|
func (a *auditService) LocalNodeInfo(ctx context.Context, req *netmap.LocalNodeInfoRequest) (*netmap.LocalNodeInfoResponse, error) {
|
||||||
|
res, err := a.next.LocalNodeInfo(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, netmapGRPC.NetmapService_LocalNodeInfo_FullMethodName, req,
|
||||||
|
nil, err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkInfo implements Server.
|
||||||
|
func (a *auditService) NetworkInfo(ctx context.Context, req *netmap.NetworkInfoRequest) (*netmap.NetworkInfoResponse, error) {
|
||||||
|
res, err := a.next.NetworkInfo(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, netmapGRPC.NetmapService_NetworkInfo_FullMethodName, req,
|
||||||
|
nil, err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Snapshot implements Server.
|
||||||
|
func (a *auditService) Snapshot(ctx context.Context, req *netmap.SnapshotRequest) (*netmap.SnapshotResponse, error) {
|
||||||
|
res, err := a.next.Snapshot(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, netmapGRPC.NetmapService_NetmapSnapshot_FullMethodName, req,
|
||||||
|
nil, err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
172
pkg/services/object/audit.go
Normal file
172
pkg/services/object/audit.go
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
package object
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object"
|
||||||
|
objectGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object/grpc"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/util"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||||
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ ServiceServer = (*auditService)(nil)
|
||||||
|
|
||||||
|
type auditService struct {
|
||||||
|
next ServiceServer
|
||||||
|
log *logger.Logger
|
||||||
|
enabled *atomic.Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuditService(next ServiceServer, log *logger.Logger, enabled *atomic.Bool) ServiceServer {
|
||||||
|
return &auditService{
|
||||||
|
next: next,
|
||||||
|
log: log,
|
||||||
|
enabled: enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete implements ServiceServer.
|
||||||
|
func (a *auditService) Delete(ctx context.Context, req *object.DeleteRequest) (*object.DeleteResponse, error) {
|
||||||
|
res, err := a.next.Delete(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, objectGRPC.ObjectService_Delete_FullMethodName, req,
|
||||||
|
audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get implements ServiceServer.
|
||||||
|
func (a *auditService) Get(req *object.GetRequest, stream GetObjectStream) error {
|
||||||
|
err := a.next.Get(req, stream)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, objectGRPC.ObjectService_Get_FullMethodName, req,
|
||||||
|
audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRange implements ServiceServer.
|
||||||
|
func (a *auditService) GetRange(req *object.GetRangeRequest, stream GetObjectRangeStream) error {
|
||||||
|
err := a.next.GetRange(req, stream)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, objectGRPC.ObjectService_GetRange_FullMethodName, req,
|
||||||
|
audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRangeHash implements ServiceServer.
|
||||||
|
func (a *auditService) GetRangeHash(ctx context.Context, req *object.GetRangeHashRequest) (*object.GetRangeHashResponse, error) {
|
||||||
|
resp, err := a.next.GetRangeHash(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, objectGRPC.ObjectService_GetRangeHash_FullMethodName, req,
|
||||||
|
audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Head implements ServiceServer.
|
||||||
|
func (a *auditService) Head(ctx context.Context, req *object.HeadRequest) (*object.HeadResponse, error) {
|
||||||
|
resp, err := a.next.Head(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, objectGRPC.ObjectService_Head_FullMethodName, req,
|
||||||
|
audit.TargetFromRef(req.GetBody().GetAddress(), &oid.Address{}), err == nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put implements ServiceServer.
|
||||||
|
func (a *auditService) Put() (PutObjectStream, error) {
|
||||||
|
res, err := a.next.Put()
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
audit.LogRequest(a.log, objectGRPC.ObjectService_Put_FullMethodName, nil, nil, false)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
return &auditPutStream{
|
||||||
|
stream: res,
|
||||||
|
log: a.log,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutSingle implements ServiceServer.
|
||||||
|
func (a *auditService) PutSingle(ctx context.Context, req *object.PutSingleRequest) (*object.PutSingleResponse, error) {
|
||||||
|
resp, err := a.next.PutSingle(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, objectGRPC.ObjectService_PutSingle_FullMethodName, req,
|
||||||
|
audit.TargetFromContainerIDObjectID(req.GetBody().GetObject().GetHeader().GetContainerID(),
|
||||||
|
req.GetBody().GetObject().GetObjectID()),
|
||||||
|
err == nil)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search implements ServiceServer.
|
||||||
|
func (a *auditService) Search(req *object.SearchRequest, stream SearchStream) error {
|
||||||
|
err := a.next.Search(req, stream)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, objectGRPC.ObjectService_Search_FullMethodName, req,
|
||||||
|
audit.TargetFromRef(req.GetBody().GetContainerID(), &cid.ID{}), err == nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ PutObjectStream = (*auditPutStream)(nil)
|
||||||
|
|
||||||
|
type auditPutStream struct {
|
||||||
|
stream PutObjectStream
|
||||||
|
log *logger.Logger
|
||||||
|
|
||||||
|
failed bool
|
||||||
|
key []byte
|
||||||
|
containerID *refs.ContainerID
|
||||||
|
objectID *refs.ObjectID
|
||||||
|
}
|
||||||
|
|
||||||
|
// CloseAndRecv implements PutObjectStream.
|
||||||
|
func (a *auditPutStream) CloseAndRecv(ctx context.Context) (*object.PutResponse, error) {
|
||||||
|
resp, err := a.stream.CloseAndRecv(ctx)
|
||||||
|
if err != nil {
|
||||||
|
a.failed = true
|
||||||
|
}
|
||||||
|
a.objectID = resp.GetBody().GetObjectID()
|
||||||
|
audit.LogRequestWithKey(a.log, objectGRPC.ObjectService_Put_FullMethodName, a.key,
|
||||||
|
audit.TargetFromContainerIDObjectID(a.containerID, a.objectID),
|
||||||
|
!a.failed)
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send implements PutObjectStream.
|
||||||
|
func (a *auditPutStream) Send(ctx context.Context, req *object.PutRequest) error {
|
||||||
|
if partInit, ok := req.GetBody().GetObjectPart().(*object.PutObjectPartInit); ok {
|
||||||
|
a.containerID = partInit.GetHeader().GetContainerID()
|
||||||
|
a.objectID = partInit.GetObjectID()
|
||||||
|
a.key = req.GetVerificationHeader().GetBodySignature().GetKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
err := a.stream.Send(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
a.failed = true
|
||||||
|
}
|
||||||
|
if !errors.Is(err, util.ErrAbortStream) { // CloseAndRecv will not be called, so log here
|
||||||
|
audit.LogRequestWithKey(a.log, objectGRPC.ObjectService_Put_FullMethodName, a.key,
|
||||||
|
audit.TargetFromContainerIDObjectID(a.containerID, a.objectID),
|
||||||
|
!a.failed)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
39
pkg/services/session/audit.go
Normal file
39
pkg/services/session/audit.go
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
|
||||||
|
sessionGRPC "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session/grpc"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ Server = (*auditService)(nil)
|
||||||
|
|
||||||
|
type auditService struct {
|
||||||
|
next Server
|
||||||
|
log *logger.Logger
|
||||||
|
enabled *atomic.Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuditService(next Server, log *logger.Logger, enabled *atomic.Bool) Server {
|
||||||
|
return &auditService{
|
||||||
|
next: next,
|
||||||
|
log: log,
|
||||||
|
enabled: enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create implements Server.
|
||||||
|
func (a *auditService) Create(ctx context.Context, req *session.CreateRequest) (*session.CreateResponse, error) {
|
||||||
|
res, err := a.next.Create(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequest(a.log, sessionGRPC.SessionService_Create_FullMethodName, req,
|
||||||
|
audit.TargetFromRef(req.GetBody().GetOwnerID(), &user.ID{}), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
135
pkg/services/tree/audit.go
Normal file
135
pkg/services/tree/audit.go
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
package tree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/audit"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ TreeServiceServer = (*auditService)(nil)
|
||||||
|
|
||||||
|
type auditService struct {
|
||||||
|
next TreeServiceServer
|
||||||
|
log *logger.Logger
|
||||||
|
enabled *atomic.Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAuditService(next TreeServiceServer, log *logger.Logger, enabled *atomic.Bool) TreeServiceServer {
|
||||||
|
return &auditService{
|
||||||
|
next: next,
|
||||||
|
log: log,
|
||||||
|
enabled: enabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add implements TreeServiceServer.
|
||||||
|
func (a *auditService) Add(ctx context.Context, req *AddRequest) (*AddResponse, error) {
|
||||||
|
res, err := a.next.Add(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, TreeService_Add_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddByPath implements TreeServiceServer.
|
||||||
|
func (a *auditService) AddByPath(ctx context.Context, req *AddByPathRequest) (*AddByPathResponse, error) {
|
||||||
|
res, err := a.next.AddByPath(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, TreeService_AddByPath_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply implements TreeServiceServer.
|
||||||
|
func (a *auditService) Apply(ctx context.Context, req *ApplyRequest) (*ApplyResponse, error) {
|
||||||
|
res, err := a.next.Apply(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, TreeService_Apply_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNodeByPath implements TreeServiceServer.
|
||||||
|
func (a *auditService) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest) (*GetNodeByPathResponse, error) {
|
||||||
|
res, err := a.next.GetNodeByPath(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, TreeService_GetNodeByPath_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOpLog implements TreeServiceServer.
|
||||||
|
func (a *auditService) GetOpLog(req *GetOpLogRequest, srv TreeService_GetOpLogServer) error {
|
||||||
|
err := a.next.GetOpLog(req, srv)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, TreeService_GetOpLog_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSubTree implements TreeServiceServer.
|
||||||
|
func (a *auditService) GetSubTree(req *GetSubTreeRequest, srv TreeService_GetSubTreeServer) error {
|
||||||
|
err := a.next.GetSubTree(req, srv)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, TreeService_GetSubTree_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Healthcheck implements TreeServiceServer.
|
||||||
|
func (a *auditService) Healthcheck(ctx context.Context, req *HealthcheckRequest) (*HealthcheckResponse, error) {
|
||||||
|
res, err := a.next.Healthcheck(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, TreeService_Healthcheck_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
nil, err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move implements TreeServiceServer.
|
||||||
|
func (a *auditService) Move(ctx context.Context, req *MoveRequest) (*MoveResponse, error) {
|
||||||
|
res, err := a.next.Move(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, TreeService_Move_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove implements TreeServiceServer.
|
||||||
|
func (a *auditService) Remove(ctx context.Context, req *RemoveRequest) (*RemoveResponse, error) {
|
||||||
|
res, err := a.next.Remove(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, TreeService_Remove_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromTreeID(req.GetBody().GetContainerId(), req.GetBody().GetTreeId()), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeList implements TreeServiceServer.
|
||||||
|
func (a *auditService) TreeList(ctx context.Context, req *TreeListRequest) (*TreeListResponse, error) {
|
||||||
|
res, err := a.next.TreeList(ctx, req)
|
||||||
|
if !a.enabled.Load() {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
audit.LogRequestWithKey(a.log, TreeService_TreeList_FullMethodName, req.GetSignature().GetKey(),
|
||||||
|
audit.TargetFromTreeID(req.GetBody().GetContainerId(), ""), err == nil)
|
||||||
|
return res, err
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue