diff --git a/.github/workflows/sentryflow-pr-checks.yml b/.github/workflows/pr-checks.yml similarity index 96% rename from .github/workflows/sentryflow-pr-checks.yml rename to .github/workflows/pr-checks.yml index 1b84c0c..99e3146 100644 --- a/.github/workflows/sentryflow-pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -1,4 +1,4 @@ -name: sentryflow-pr-checks +name: pr-checks on: pull_request: diff --git a/.github/workflows/sentryflow-release-image.yml b/.github/workflows/release.yml similarity index 97% rename from .github/workflows/sentryflow-release-image.yml rename to .github/workflows/release.yml index e53fffc..904b408 100644 --- a/.github/workflows/sentryflow-release-image.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: sentryflow-release-image +name: release on: push: diff --git a/README.md b/README.md index 8e7a250..ca7b821 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,26 @@ # SentryFlow -[![SentryFlow Docker Build](https://github.com/boanlab/numbat/actions/workflows/sentryflow-release-image.yml/badge.svg)](https://github.com/boanlab/numbat/actions/workflows/sentryflow-release-image.yml) [![CI for SentryFlow](https://github.com/boanlab/numbat/actions/workflows/ci-test-go.yml/badge.svg)](https://github.com/boanlab/numbat/actions/workflows/ci-test-go.yml) [![CI for AI](https://github.com/boanlab/sentryflow/actions/workflows/ci-test-py.yml/badge.svg)](https://github.com/boanlab/sentryflow/actions/workflows/ci-test-py.yml) +[![SentryFlow Docker Build](https://github.com/boanlab/sentryflow/actions/workflows/release.yml/badge.svg)](https://github.com/boanlab/sentryflow/actions/workflows/release.yml) [![CI for SentryFlow](https://github.com/boanlab/sentryflow/actions/workflows/ci-test-go.yml/badge.svg)](https://github.com/boanlab/sentryflow/actions/workflows/ci-test-go.yml) [![CI for AI Engine](https://github.com/boanlab/sentryflow/actions/workflows/ci-test-py.yml/badge.svg)](https://github.com/boanlab/sentryflow/actions/workflows/ci-test-py.yml) SentryFlow is a cloud-native system for API observability and security, specializing in log collection, metric production, and data exportation. ## Architecture Overview -![Numbat_Overview](docs/sentryflow_overview.png) +![SentryFlow_Overview](docs/sentryflow_overview.png) ### Features + - Generation of API Access Logs -- Proudction of API Metrics and Statistics -- Inference of API Specifications +- Production of API Metrics +- AI-driven API Classification (Inference) ## Documentation ### Basic Information + - [Getting Started](docs/getting_started.md) - [Use Cases](examples/README.md) ### Contribution + - [Contribution Guide](contribution/README.md) diff --git a/ai-engine/Dockerfile b/ai-engine/Dockerfile index b4022d0..7740ed5 100644 --- a/ai-engine/Dockerfile +++ b/ai-engine/Dockerfile @@ -1,6 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -# Dockerfile FROM ubuntu:22.04 RUN apt-get update diff --git a/ai-engine/ai_engine.py b/ai-engine/ai_engine.py index 55f3536..3d63946 100644 --- a/ai-engine/ai_engine.py +++ b/ai-engine/ai_engine.py @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 -"""SentryFlow AI API Classification Engine""" +"""SentryFlow AI Engine for API Classification""" from concurrent import futures from collections import Counter @@ -8,8 +8,9 @@ import os import grpc -from protobuf import sentryflow_metrics_pb2_grpc from protobuf import sentryflow_metrics_pb2 +from protobuf import sentryflow_metrics_pb2_grpc + from stringlifier.api import Stringlifier @@ -18,21 +19,21 @@ class HandlerServer: Class for gRPC Servers """ def __init__(self): + self.server = None + self.grpc_servers = [] + try: - self.listen_addr = os.environ["AI_ENGINE_ADDRESS"] + self.listen_addr = os.environ["AI_ENGINE"] except KeyError: self.listen_addr = "0.0.0.0:5000" - self.server = None - self.grpc_servers = [] - def init_grpc_servers(self): """ init_grpc_servers method that initializes and registers gRPC servers :return: None """ self.server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) - self.grpc_servers.append(APIClassificationServer()) # @todo: make this configurable + self.grpc_servers.append(APIClassificationServer()) grpc_server: GRPCServer for grpc_server in self.grpc_servers: @@ -40,12 +41,13 @@ def init_grpc_servers(self): def serve(self): """ - serve method that starts serving gRPC servers, this is blocking function. + serve method that starts serving the gRPC servers (blocking function) :return: None """ self.server.add_insecure_port(self.listen_addr) print(f"[INFO] Starting to serve on {self.listen_addr}") + self.server.start() self.server.wait_for_termination() @@ -73,7 +75,6 @@ class APIClassificationServer(sentryflow_metrics_pb2_grpc.APIClassificationServi """ Class for API Classification Server using Stringlifier """ - def __init__(self): self.stringlifier = Stringlifier() print("[Init] Successfully initialized APIClassificationServer") @@ -83,15 +84,13 @@ def register(self, server): def ClassifyAPIs(self, request_iterator, _): # pylint: disable=C0103 """ - GetAPIClassification method that runs multiple API ML Classification at once + ClassifyAPIs method that runs multiple MLs for API Classification at once :param request_iterator: The requests :param context: The context :return: The results """ - for req in request_iterator: all_paths = req.API - # for paths in all_paths: ml_results = self.stringlifier(all_paths) ml_counts = Counter(ml_results) diff --git a/clients/log-client/client/client.go b/clients/log-client/client/client.go index 61d8dbe..021acbd 100644 --- a/clients/log-client/client/client.go +++ b/clients/log-client/client/client.go @@ -68,7 +68,7 @@ func NewClient(client pb.SentryFlowClient, clientInfo *pb.ClientInfo, logCfg str // Contact the server and print out its response logStream, err := client.GetAPILog(context.Background(), clientInfo) if err != nil { - log.Fatalf("[Client] Could not get log: %v", err) + log.Fatalf("[Client] Could not get API log: %v", err) } fd.logStream = logStream @@ -77,7 +77,7 @@ func NewClient(client pb.SentryFlowClient, clientInfo *pb.ClientInfo, logCfg str if metricCfg != "none" && (metricFilter == "all" || metricFilter == "api") { amStream, err := client.GetAPIMetrics(context.Background(), clientInfo) if err != nil { - log.Fatalf("[Client] Could not get log: %v", err) + log.Fatalf("[Client] Could not get API metrics: %v", err) } fd.apiMetricStream = amStream @@ -86,7 +86,7 @@ func NewClient(client pb.SentryFlowClient, clientInfo *pb.ClientInfo, logCfg str if metricCfg != "none" && (metricFilter == "all" || metricFilter == "envoy") { emStream, err := client.GetEnvoyMetrics(context.Background(), clientInfo) if err != nil { - log.Fatalf("[Client] Could not get log: %v", err) + log.Fatalf("[Client] Could not get Enovy metrics: %v", err) } fd.envoyMetricStream = emStream @@ -95,18 +95,19 @@ func NewClient(client pb.SentryFlowClient, clientInfo *pb.ClientInfo, logCfg str return fd } -// LogRoutine Function -func (fd *Feeder) LogRoutine(logCfg string) { +// APILogRoutine Function +func (fd *Feeder) APILogRoutine(logCfg string) { for fd.Running { select { default: data, err := fd.logStream.Recv() if err != nil { - log.Fatalf("[Client] Failed to receive a log: %v", err) + log.Fatalf("[Client] Failed to receive an API log: %v", err) break } + str := "" - str = str + "== Access Log ==\n" + str = str + "== API Log ==\n" str = str + fmt.Sprintf("%v\n", data) if logCfg == "stdout" { @@ -120,14 +121,14 @@ func (fd *Feeder) LogRoutine(logCfg string) { } } -// APIMetricRoutine Function -func (fd *Feeder) APIMetricRoutine(metricCfg string) { +// APIMetricsRoutine Function +func (fd *Feeder) APIMetricsRoutine(metricCfg string) { for fd.Running { select { default: data, err := fd.apiMetricStream.Recv() if err != nil { - log.Fatalf("[Client] Failed to receive metrics: %v", err) + log.Fatalf("[Client] Failed to receive API metrics: %v", err) break } @@ -146,15 +147,15 @@ func (fd *Feeder) APIMetricRoutine(metricCfg string) { } } -// EnvoyMetricRoutine Function -func (fd *Feeder) EnvoyMetricRoutine(metricCfg string) { +// EnvoyMetricsRoutine Function +func (fd *Feeder) EnvoyMetricsRoutine(metricCfg string) { metricKeys := []string{"GAUGE", "COUNTER", "HISTOGRAM", "SUMMARY"} for fd.Running { select { default: data, err := fd.envoyMetricStream.Recv() if err != nil { - log.Fatalf("[Client] Failed to receive metrics: %v", err) + log.Fatalf("[Client] Failed to receive Envoy metrics: %v", err) break } diff --git a/clients/log-client/go.mod b/clients/log-client/go.mod index f50117f..547fa62 100644 --- a/clients/log-client/go.mod +++ b/clients/log-client/go.mod @@ -14,5 +14,5 @@ require ( golang.org/x/sys v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/protobuf v1.34.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect ) diff --git a/clients/log-client/go.sum b/clients/log-client/go.sum index 84d0dd0..c475bdd 100644 --- a/clients/log-client/go.sum +++ b/clients/log-client/go.sum @@ -10,5 +10,5 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= -google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= -google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= diff --git a/clients/log-client/main.go b/clients/log-client/main.go index f39c867..a177cd9 100644 --- a/clients/log-client/main.go +++ b/clients/log-client/main.go @@ -28,9 +28,9 @@ func main() { } // Get arguments - logCfgPtr := flag.String("logCfg", "stdout", "Output location for logs, {stdout|file|none}") - metricCfgPtr := flag.String("metricCfg", "stdout", "Output location for envoy metrics and api metrics, {stdout|file|none}") - metricFilterPtr := flag.String("metricFilter", "envoy", "Filter for what kinds of envoy and api metric to receive, {api|policy|envoy}") + logCfgPtr := flag.String("logCfg", "stdout", "Output location for API logs, {stdout|file|none}") + metricCfgPtr := flag.String("metricCfg", "stdout", "Output location for API and Envoy metrics, {stdout|file|none}") + metricFilterPtr := flag.String("metricFilter", "envoy", "Filter to select specific API or Envoy metrics to receive, {api|envoy}") flag.Parse() if *logCfgPtr == "none" && *metricCfgPtr == "none" { @@ -67,7 +67,7 @@ func main() { defer conn.Close() // Connected to the gRPC server - log.Printf("[gRPC] Started to collect Access Logs from %s", addr) + log.Printf("[gRPC] Started to collect Logs from %s", addr) // Define clientInfo clientInfo := &protobuf.ClientInfo{ @@ -81,18 +81,18 @@ func main() { logClient := client.NewClient(sfClient, clientInfo, *logCfgPtr, *metricCfgPtr, *metricFilterPtr) if *logCfgPtr != "none" { - go logClient.LogRoutine(*logCfgPtr) + go logClient.APILogRoutine(*logCfgPtr) fmt.Printf("[APILog] Started to watch API logs\n") } if *metricCfgPtr != "none" { if *metricFilterPtr == "all" || *metricFilterPtr == "api" { - go logClient.APIMetricRoutine(*metricCfgPtr) + go logClient.APIMetricsRoutine(*metricCfgPtr) fmt.Printf("[Metric] Started to watch API Metrics\n") } if *metricFilterPtr == "all" || *metricFilterPtr == "envoy" { - go logClient.EnvoyMetricRoutine(*metricCfgPtr) + go logClient.EnvoyMetricsRoutine(*metricCfgPtr) fmt.Printf("[Metric] Started to watch Envoy Metrics\n") } } diff --git a/clients/mongo-client/client/client.go b/clients/mongo-client/client/client.go index 46e046b..bbef3a5 100644 --- a/clients/mongo-client/client/client.go +++ b/clients/mongo-client/client/client.go @@ -18,7 +18,7 @@ type Feeder struct { envoyMetricStream pb.SentryFlow_GetEnvoyMetricsClient apiMetricStream pb.SentryFlow_GetAPIMetricsClient - dbHandler mongodb.MongoDBHandler + dbHandler mongodb.DBHandler Done chan struct{} } @@ -28,16 +28,14 @@ func NewClient(client pb.SentryFlowClient, clientInfo *pb.ClientInfo, logCfg str fd := &Feeder{} fd.Running = true - fd.client = client - fd.Done = make(chan struct{}) if logCfg != "none" { // Contact the server and print out its response logStream, err := client.GetAPILog(context.Background(), clientInfo) if err != nil { - log.Fatalf("[Client] Could not get log: %v", err) + log.Fatalf("[Client] Could not get API log: %v", err) } fd.logStream = logStream @@ -46,7 +44,7 @@ func NewClient(client pb.SentryFlowClient, clientInfo *pb.ClientInfo, logCfg str if metricCfg != "none" && (metricFilter == "all" || metricFilter == "api") { amStream, err := client.GetAPIMetrics(context.Background(), clientInfo) if err != nil { - log.Fatalf("[Client] Could not get log: %v", err) + log.Fatalf("[Client] Could not get API metrics: %v", err) } fd.apiMetricStream = amStream @@ -55,7 +53,7 @@ func NewClient(client pb.SentryFlowClient, clientInfo *pb.ClientInfo, logCfg str if metricCfg != "none" && (metricFilter == "all" || metricFilter == "envoy") { emStream, err := client.GetEnvoyMetrics(context.Background(), clientInfo) if err != nil { - log.Fatalf("[Client] Could not get log: %v", err) + log.Fatalf("[Client] Could not get Envoy metrics: %v", err) } fd.envoyMetricStream = emStream @@ -71,19 +69,19 @@ func NewClient(client pb.SentryFlowClient, clientInfo *pb.ClientInfo, logCfg str return fd } -// LogRoutine Function -func (fd *Feeder) LogRoutine(logCfg string) { +// APILogRoutine Function +func (fd *Feeder) APILogRoutine(logCfg string) { for fd.Running { select { default: data, err := fd.logStream.Recv() if err != nil { - log.Fatalf("[Client] Failed to receive a log: %v", err) + log.Fatalf("[Client] Failed to receive an API log: %v", err) break } err = fd.dbHandler.InsertAPILog(data) if err != nil { - log.Fatalf("[MongoDB] Failed to insert API Log: %v", err) + log.Fatalf("[MongoDB] Failed to insert an API log: %v", err) } case <-fd.Done: return @@ -91,19 +89,19 @@ func (fd *Feeder) LogRoutine(logCfg string) { } } -// APIMetricRoutine Function -func (fd *Feeder) APIMetricRoutine(metricCfg string) { +// APIMetricsRoutine Function +func (fd *Feeder) APIMetricsRoutine(metricCfg string) { for fd.Running { select { default: data, err := fd.apiMetricStream.Recv() if err != nil { - log.Fatalf("[Client] Failed to receive metrics: %v", err) + log.Fatalf("[Client] Failed to receive API metrics: %v", err) break } err = fd.dbHandler.InsertAPIMetrics(data) if err != nil { - log.Fatalf("[MongoDB] Failed to insert API Metrics: %v", err) + log.Fatalf("[MongoDB] Failed to insert API metrics: %v", err) } case <-fd.Done: return @@ -111,19 +109,19 @@ func (fd *Feeder) APIMetricRoutine(metricCfg string) { } } -// EnvoyMetricRoutine Function -func (fd *Feeder) EnvoyMetricRoutine(metricCfg string) { +// EnvoyMetricsRoutine Function +func (fd *Feeder) EnvoyMetricsRoutine(metricCfg string) { for fd.Running { select { default: data, err := fd.envoyMetricStream.Recv() if err != nil { - log.Fatalf("[Client] Failed to receive metrics: %v", err) + log.Fatalf("[Client] Failed to receive Envoy metrics: %v", err) break } err = fd.dbHandler.InsertEnvoyMetrics(data) if err != nil { - log.Fatalf("[MongoDB] Failed to insert Envoy Metrics: %v", err) + log.Fatalf("[MongoDB] Failed to insert Envoy metrics: %v", err) } case <-fd.Done: return diff --git a/clients/mongo-client/go.mod b/clients/mongo-client/go.mod index d3fb274..cbef0f4 100644 --- a/clients/mongo-client/go.mod +++ b/clients/mongo-client/go.mod @@ -24,5 +24,5 @@ require ( golang.org/x/sys v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/protobuf v1.34.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect ) diff --git a/clients/mongo-client/go.sum b/clients/mongo-client/go.sum index 81602be..bd34782 100644 --- a/clients/mongo-client/go.sum +++ b/clients/mongo-client/go.sum @@ -63,5 +63,5 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= -google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= -google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= diff --git a/clients/mongo-client/main.go b/clients/mongo-client/main.go index 1e35a85..95dea38 100644 --- a/clients/mongo-client/main.go +++ b/clients/mongo-client/main.go @@ -4,6 +4,7 @@ package main import ( protobuf "SentryFlow/protobuf" + "flag" "fmt" "log" @@ -29,8 +30,8 @@ func main() { // Get arguments logCfgPtr := flag.String("logCfg", "mongodb", "Location for storing API logs, {mongodb|none}") - metricCfgPtr := flag.String("metricCfg", "mongodb", "Location for storing API metrics or Envoy metrics, {mongodb|none}") - metricFilterPtr := flag.String("metricFilter", "envoy", "Filter for where to receive metrics, {api|envoy}") + metricCfgPtr := flag.String("metricCfg", "mongodb", "Location for storing API and Envoy metrics, {mongodb|none}") + metricFilterPtr := flag.String("metricFilter", "envoy", "Filter to select specific API or Envoy metrics to receive, {api|envoy}") mongoDBAddrPtr := flag.String("mongodb", "", "MongoDB Server Address") flag.Parse() @@ -71,7 +72,7 @@ func main() { defer conn.Close() // Connected to the gRPC server - log.Printf("[gRPC] Started to collect Access Logs from %s", addr) + log.Printf("[gRPC] Started to collect Logs from %s", addr) // Define clientInfo clientInfo := &protobuf.ClientInfo{ @@ -85,19 +86,19 @@ func main() { logClient := client.NewClient(sfClient, clientInfo, *logCfgPtr, *metricCfgPtr, *metricFilterPtr, *mongoDBAddrPtr) if *logCfgPtr != "none" { - go logClient.LogRoutine(*logCfgPtr) + go logClient.APILogRoutine(*logCfgPtr) fmt.Printf("[APILog] Started to watch API logs\n") } if *metricCfgPtr != "none" { if *metricFilterPtr == "all" || *metricFilterPtr == "api" { - go logClient.APIMetricRoutine(*metricCfgPtr) - fmt.Printf("[Metric] Started to watch api metrics\n") + go logClient.APIMetricsRoutine(*metricCfgPtr) + fmt.Printf("[Metric] Started to watch API metrics\n") } if *metricFilterPtr == "all" || *metricFilterPtr == "envoy" { - go logClient.EnvoyMetricRoutine(*metricCfgPtr) - fmt.Printf("[Metric] Started to watch envoy metrics\n") + go logClient.EnvoyMetricsRoutine(*metricCfgPtr) + fmt.Printf("[Metric] Started to watch Envoy metrics\n") } } diff --git a/clients/mongo-client/mongodb/mongoHandler.go b/clients/mongo-client/mongodb/mongoHandler.go index a92e156..eaedb76 100644 --- a/clients/mongo-client/mongodb/mongoHandler.go +++ b/clients/mongo-client/mongodb/mongoHandler.go @@ -14,21 +14,22 @@ import ( "go.mongodb.org/mongo-driver/mongo/options" ) -// MongoDBHandler Structure -type MongoDBHandler struct { +// DBHandler Structure +type DBHandler struct { client *mongo.Client cancel context.CancelFunc - database *mongo.Database - apiLogCol *mongo.Collection - metricsCol *mongo.Collection + database *mongo.Database + apiLogCol *mongo.Collection + apiMetricsCol *mongo.Collection + evyMetricsCol *mongo.Collection } -// dbHandler structure -var dbHandler MongoDBHandler +// dbHandler for Global Reference +var dbHandler DBHandler -// New creates a new mongoDB handler -func NewMongoDBHandler(mongoDBAddr string) (*MongoDBHandler, error) { +// NewMongoDBHandler Function +func NewMongoDBHandler(mongoDBAddr string) (*DBHandler, error) { var err error // Create a MongoDB client @@ -54,21 +55,22 @@ func NewMongoDBHandler(mongoDBAddr string) (*MongoDBHandler, error) { // Create APILogs and Metrics collections dbHandler.apiLogCol = dbHandler.database.Collection("APILogs") - dbHandler.metricsCol = dbHandler.database.Collection("Metrics") + dbHandler.apiMetricsCol = dbHandler.database.Collection("APIMetrics") + dbHandler.evyMetricsCol = dbHandler.database.Collection("EnvoyMetrics") return &dbHandler, nil } -// Disconnect function -func (handler *MongoDBHandler) Disconnect() { +// Disconnect Function +func (handler *DBHandler) Disconnect() { err := handler.client.Disconnect(context.Background()) if err != nil { log.Printf("[MongoDB] Unable to properly disconnect: %v", err) } } -// InsertAl function -func (handler *MongoDBHandler) InsertAPILog(data *protobuf.APILog) error { +// InsertAPILog Function +func (handler *DBHandler) InsertAPILog(data *protobuf.APILog) error { _, err := handler.apiLogCol.InsertOne(context.Background(), data) if err != nil { return err @@ -77,9 +79,9 @@ func (handler *MongoDBHandler) InsertAPILog(data *protobuf.APILog) error { return nil } -// InsertMetrics function -func (handler *MongoDBHandler) InsertAPIMetrics(data *protobuf.APIMetrics) error { - _, err := handler.metricsCol.InsertOne(context.Background(), data) +// InsertAPIMetrics Function +func (handler *DBHandler) InsertAPIMetrics(data *protobuf.APIMetrics) error { + _, err := handler.apiMetricsCol.InsertOne(context.Background(), data) if err != nil { return err } @@ -87,9 +89,9 @@ func (handler *MongoDBHandler) InsertAPIMetrics(data *protobuf.APIMetrics) error return nil } -// InsertMetrics function -func (handler *MongoDBHandler) InsertEnvoyMetrics(data *protobuf.EnvoyMetrics) error { - _, err := handler.metricsCol.InsertOne(context.Background(), data) +// InsertEnvoyMetrics Function +func (handler *DBHandler) InsertEnvoyMetrics(data *protobuf.EnvoyMetrics) error { + _, err := handler.evyMetricsCol.InsertOne(context.Background(), data) if err != nil { return err } diff --git a/deployments/ai-engine.yaml b/deployments/ai-engine.yaml index 78c65c5..cce9e45 100644 --- a/deployments/ai-engine.yaml +++ b/deployments/ai-engine.yaml @@ -17,9 +17,9 @@ spec: - name: sentryflow image: 5gsec/sentryflow-ai-engine:v0.1 ports: - - containerPort: 5000 + - name: ai-engine protocol: TCP - name: ai-engine + containerPort: 5000 --- apiVersion: v1 kind: Service @@ -30,7 +30,7 @@ spec: selector: app: ai-engine ports: - - protocol: TCP - port: 5000 - targetPort: 5000 - name: sentryflow-ai-engine + - name: sentryflow-ai-engine + protocol: TCP + port: 5000 + targetPort: 5000 diff --git a/deployments/mongo-client.yaml b/deployments/mongo-client.yaml index 6e800d0..698ed46 100644 --- a/deployments/mongo-client.yaml +++ b/deployments/mongo-client.yaml @@ -14,10 +14,10 @@ spec: app: mongodb spec: containers: - - name: mongodb - image: mongo:latest - ports: - - containerPort: 27017 + - name: mongodb + image: mongo:latest + ports: + - containerPort: 27017 --- apiVersion: v1 kind: Service @@ -28,9 +28,9 @@ spec: selector: app: mongodb ports: - - protocol: TCP - port: 27017 - targetPort: 27017 + - protocol: TCP + port: 27017 + targetPort: 27017 --- apiVersion: apps/v1 kind: Deployment @@ -48,7 +48,7 @@ spec: app: mongo-client spec: imagePullSecrets: - - name: regcred + - name: regcred containers: - name: mongo-client image: 5gsec/sentryflow-mongo-client:v0.1 diff --git a/deployments/relay-client.yaml b/deployments/relay-client.yaml deleted file mode 100644 index f76db66..0000000 --- a/deployments/relay-client.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: relay-client - namespace: sentryflow -spec: - replicas: 1 - selector: - matchLabels: - app: relay-client - template: - metadata: - labels: - app: relay-client - spec: - containers: - - name: relay-client - image: 5gsec/sentryflow-relay-client:v0.1 - ports: - - containerPort: 8080 - protocol: TCP - name: grpc - env: - - name: SERVER_ADDR - value: "sentryflow.sentryflow.svc.cluster.local" - - name: SERVER_PORT - value: "8080" - - name: METRIC_FILTER - value: "envoy" - - name: LOG_CFG - value: "stdout" - - name: METRIC_CFG - value: "stdout" diff --git a/deployments/sentryflow.yaml b/deployments/sentryflow.yaml index 6fdcfed..d38da78 100644 --- a/deployments/sentryflow.yaml +++ b/deployments/sentryflow.yaml @@ -3,7 +3,7 @@ kind: Namespace metadata: name: sentryflow labels: - istio-injection: disabled # avoid Istio sidecar injection + istio-injection: disabled # avoid Istio sidecar-injection pod-security.kubernetes.io/audit: privileged pod-security.kubernetes.io/enforce: privileged pod-security.kubernetes.io/warn: privileged @@ -56,12 +56,12 @@ spec: - name: sentryflow image: 5gsec/sentryflow:v0.1 ports: - - containerPort: 4317 + - name: otel-grpc protocol: TCP - name: otel-grpc - - containerPort: 8080 + containerPort: 4317 + - name: sentryflow-grpc protocol: TCP - name: sentryflow-grpc + containerPort: 8080 --- apiVersion: v1 kind: Service @@ -72,11 +72,11 @@ spec: selector: app: sentryflow ports: - - protocol: TCP - port: 4317 - targetPort: 4317 - name: otel-grpc - - protocol: TCP - port: 8080 - targetPort: 8080 - name: sentryflow-grpc + - name: otel-grpc + protocol: TCP + port: 4317 + targetPort: 4317 + - name: sentryflow-grpc + protocol: TCP + port: 8080 + targetPort: 8080 diff --git a/protobuf/go.mod b/protobuf/go.mod index 0b4c987..2038b4d 100644 --- a/protobuf/go.mod +++ b/protobuf/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( google.golang.org/grpc v1.63.2 - google.golang.org/protobuf v1.34.0 + google.golang.org/protobuf v1.34.1 ) require ( diff --git a/protobuf/go.sum b/protobuf/go.sum index 84d0dd0..c475bdd 100644 --- a/protobuf/go.sum +++ b/protobuf/go.sum @@ -10,5 +10,5 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= -google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= -google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= diff --git a/sentryflow/Makefile b/sentryflow/Makefile index dab6b13..91e228c 100644 --- a/sentryflow/Makefile +++ b/sentryflow/Makefile @@ -5,7 +5,7 @@ IMAGE_NAME = 5gsec/$(PROG_NAME) TAG = v0.1 .PHONY: build -build: +build: gofmt golint gosec go mod tidy go build -o $(PROG_NAME) diff --git a/sentryflow/collector/collectorHandler.go b/sentryflow/collector/collectorHandler.go index 58a8ef3..0309a6c 100644 --- a/sentryflow/collector/collectorHandler.go +++ b/sentryflow/collector/collectorHandler.go @@ -25,7 +25,6 @@ func init() { type ColHandler struct { colService net.Listener grpcServer *grpc.Server - collectors []collectorInterface } @@ -34,7 +33,6 @@ func NewCollectorHandler() *ColHandler { ch := &ColHandler{ collectors: make([]collectorInterface, 0), } - return ch } diff --git a/sentryflow/collector/envoy.go b/sentryflow/collector/envoy.go index 2103d54..2cfe997 100644 --- a/sentryflow/collector/envoy.go +++ b/sentryflow/collector/envoy.go @@ -116,7 +116,7 @@ func (evyAccLogs *EnvoyAccessLogsServer) StreamAccessLogs(stream envoyAccLogs.Ac if err == io.EOF { return nil } else if err != nil { - log.Printf("[EnvoyAPILogs] Something went on wrong when receiving event: %v", err) + log.Printf("[EnvoyAPILogs] Something went on wrong when receiving an event: %v", err) return err } diff --git a/sentryflow/collector/opentelemetry.go b/sentryflow/collector/opentelemetry.go index 532e1ae..05f9830 100644 --- a/sentryflow/collector/opentelemetry.go +++ b/sentryflow/collector/opentelemetry.go @@ -44,7 +44,7 @@ func generateAPILogsFromOtel(logText string) []*protobuf.APILog { logText = strings.ReplaceAll(logText, `\"`, "") logText = strings.ReplaceAll(logText, `}`, "") - // Split logs by log_records, this is single access log instance + // Split logs by log_records, this is a single access log instance parts := strings.Split(logText, "log_records") if len(parts) == 0 { return nil diff --git a/sentryflow/config/config.go b/sentryflow/config/config.go index 21ad1c6..03fa377 100644 --- a/sentryflow/config/config.go +++ b/sentryflow/config/config.go @@ -22,13 +22,13 @@ type SentryFlowConfig struct { PatchingNamespaces bool // Enable/Disable patching namespaces with 'istio-injection' RestartingPatchedDeployments bool // Enable/Disable restarting deployments after patching - AIEngineService string - AIEngineServicePort string - AIEngineBatchSize int - AggregationPeriod int // Period for aggregating metrics CleanUpPeriod int // Period for cleaning up outdated metrics + AIEngineService string // Address for AI Engine + AIEngineServicePort string // Port for AI Engine + AIEngineBatchSize int // Batch Size to send APIs to AI Engine + Debug bool // Enable/Disable SentryFlow debug mode } @@ -51,13 +51,13 @@ const ( PatchingNamespaces string = "patchingNamespaces" RestartingPatchedDeployments string = "restartingPatchedDeployments" + AggregationPeriod string = "aggregationPeriod" + CleanUpPeriod string = "cleanUpPeriod" + AIEngineService string = "aiEngineService" AIEngineServicePort string = "aiEngineServicePort" AIEngineBatchSize string = "aiEngineBatchSize" - AggregationPeriod string = "aggregationPeriod" - CleanUpPeriod string = "cleanUpPeriod" - Debug string = "debug" ) @@ -71,13 +71,13 @@ func readCmdLineParams() { patchingNamespacesB := flag.Bool(PatchingNamespaces, false, "Enable patching 'istio-injection' to all namespaces") restartingPatchedDeploymentsB := flag.Bool(RestartingPatchedDeployments, false, "Enable restarting the deployments in all patched namespaces") - aiEngineServiceStr := flag.String(AIEngineService, "ai-engine.sentryflow.svc.cluster.local", "Service address for SentryFlow AI Engine") - aiEngineServicePortStr := flag.String(AIEngineServicePort, "5000", "Service Port for SentryFlow AI Engine") - aiEngineBatchSizeInt := flag.Int(AIEngineBatchSize, 5, "Batch size for SentryFlow AI Engine") - aggregationPeriodInt := flag.Int(AggregationPeriod, 1, "Period for aggregating metrics") cleanUpPeriodInt := flag.Int(CleanUpPeriod, 5, "Period for cleanning up outdated metrics") + aiEngineServiceStr := flag.String(AIEngineService, "ai-engine.sentryflow.svc.cluster.local", "Address for SentryFlow AI Engine") + aiEngineServicePortStr := flag.String(AIEngineServicePort, "5000", "Port for SentryFlow AI Engine") + aiEngineBatchSizeInt := flag.Int(AIEngineBatchSize, 5, "Batch size to send APIs to SentryFlow AI Engine") + configDebugB := flag.Bool(Debug, false, "Enable debugging mode") var flags []string @@ -98,13 +98,13 @@ func readCmdLineParams() { viper.SetDefault(PatchingNamespaces, *patchingNamespacesB) viper.SetDefault(RestartingPatchedDeployments, *restartingPatchedDeploymentsB) + viper.SetDefault(AggregationPeriod, *aggregationPeriodInt) + viper.SetDefault(CleanUpPeriod, *cleanUpPeriodInt) + viper.SetDefault(AIEngineService, *aiEngineServiceStr) viper.SetDefault(AIEngineServicePort, *aiEngineServicePortStr) viper.SetDefault(AIEngineBatchSize, *aiEngineBatchSizeInt) - viper.SetDefault(AggregationPeriod, *aggregationPeriodInt) - viper.SetDefault(CleanUpPeriod, *cleanUpPeriodInt) - viper.SetDefault(Debug, *configDebugB) } @@ -125,13 +125,13 @@ func LoadConfig() error { GlobalConfig.PatchingNamespaces = viper.GetBool(PatchingNamespaces) GlobalConfig.RestartingPatchedDeployments = viper.GetBool(RestartingPatchedDeployments) + GlobalConfig.AggregationPeriod = viper.GetInt(AggregationPeriod) + GlobalConfig.CleanUpPeriod = viper.GetInt(CleanUpPeriod) + GlobalConfig.AIEngineService = viper.GetString(AIEngineService) GlobalConfig.AIEngineServicePort = viper.GetString(AIEngineServicePort) GlobalConfig.AIEngineBatchSize = viper.GetInt(AIEngineBatchSize) - GlobalConfig.AggregationPeriod = viper.GetInt(AggregationPeriod) - GlobalConfig.CleanUpPeriod = viper.GetInt(CleanUpPeriod) - GlobalConfig.Debug = viper.GetBool(Debug) log.Printf("Configuration [%+v]", GlobalConfig) diff --git a/sentryflow/exporter/exportAPIMetrics.go b/sentryflow/exporter/exportAPIMetrics.go index d289c32..078c7ca 100644 --- a/sentryflow/exporter/exportAPIMetrics.go +++ b/sentryflow/exporter/exportAPIMetrics.go @@ -78,8 +78,8 @@ func (exp *ExpHandler) SendAPIMetrics(apiMetrics *protobuf.APIMetrics) error { // UpdateStats Function func UpdateStats(namespace string, label string, api string) { - // == // ExpH.statsPerLabelLock.RLock() + defer ExpH.statsPerLabelLock.RUnlock() // Check if namespace+label exists if _, ok := ExpH.statsPerLabel[namespace+label]; !ok { @@ -100,16 +100,11 @@ func UpdateStats(namespace string, label string, api string) { statsPerLabel.APIs[api] = init } else { stats := statsPerLabel.APIs[api] - stats.Count++ - statsPerLabel.APIs[api] = stats } ExpH.statsPerLabel[namespace+label] = statsPerLabel - - ExpH.statsPerLabelLock.RUnlock() - // == // } // AggregateAPIMetrics Function @@ -132,7 +127,6 @@ func AggregateAPIMetrics() { if len(APIMetrics) > 0 { err := ExpH.SendAPIMetrics(&protobuf.APIMetrics{PerAPICounts: APIMetrics}) - if err != nil { log.Printf("[Envoy] Something went on wrong when Send API Metrics: %v", err) return diff --git a/sentryflow/go.mod b/sentryflow/go.mod index 2b8f325..f127fbe 100644 --- a/sentryflow/go.mod +++ b/sentryflow/go.mod @@ -64,7 +64,7 @@ require ( google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect - google.golang.org/protobuf v1.34.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/sentryflow/go.sum b/sentryflow/go.sum index 55a94cd..e02a5de 100644 --- a/sentryflow/go.sum +++ b/sentryflow/go.sum @@ -190,8 +190,8 @@ google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= -google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/sentryflow/k8s/istioPatcher.go b/sentryflow/k8s/istioPatcher.go index 4c37696..c669c9e 100644 --- a/sentryflow/k8s/istioPatcher.go +++ b/sentryflow/k8s/istioPatcher.go @@ -4,10 +4,10 @@ package k8s import ( "errors" - "fmt" + "log" + "gopkg.in/yaml.v2" "k8s.io/apimachinery/pkg/util/json" - "log" ) // meshConfig structure @@ -21,18 +21,22 @@ type meshConfig struct { Address string `yaml:"address"` } `yaml:"envoyMetricsService"` } `yaml:"defaultConfig"` + DefaultProviders struct { AccessLogs []string `yaml:"accessLogs"` Metrics []string `yaml:"metrics"` } `yaml:"defaultProviders"` + EnableEnvoyAccessLogService bool `yaml:"enableEnvoyAccessLogService"` - ExtensionProviders []struct { + + ExtensionProviders []struct { EnvoyOtelAls struct { Port string `yaml:"port"` Service string `yaml:"service"` } `yaml:"envoyOtelAls"` Name string `yaml:"name"` } `yaml:"extensionProviders"` + ExtraFields map[string]interface{} `yaml:",inline"` // all extra fields that SentryFlow will not touch } @@ -73,7 +77,6 @@ func PatchIstioConfigMap() bool { }, Name: "sentryflow", } - meshCfg.ExtensionProviders = append(meshCfg.ExtensionProviders, sfOtelAl) } @@ -90,7 +93,7 @@ func PatchIstioConfigMap() bool { return false } - strMeshCfg := fmt.Sprintf("%s", yamlMeshCfg) + strMeshCfg := string(yamlMeshCfg[:]) err = K8sH.updateConfigMap("istio-system", "istio", strMeshCfg) if err != nil { log.Printf("[PatchIstioConfigMap] Unable to update Istio ConfigMap: %v", err) @@ -98,6 +101,7 @@ func PatchIstioConfigMap() bool { } log.Printf("[PatchIstioConfigMap] Successfully patched Istio ConfigMap") + return true } @@ -140,7 +144,6 @@ func UnpatchIstioConfigMap() bool { tmp = append(tmp, provider) } } - meshCfg.DefaultProviders.AccessLogs = tmp } @@ -154,7 +157,7 @@ func UnpatchIstioConfigMap() bool { return false } - strMeshCfg := fmt.Sprintf("%s", yamlMeshCfg) + strMeshCfg := string(yamlMeshCfg[:]) err = K8sH.updateConfigMap("istio-system", "istio", strMeshCfg) if err != nil { log.Printf("[PatchIstioConfigMap] Unable to update Istio ConfigMap: %v", err) @@ -234,7 +237,7 @@ func isIstioAlreadyPatched(meshCfg meshConfig) bool { return false } - if meshCfg.EnableEnvoyAccessLogService != true { + if !meshCfg.EnableEnvoyAccessLogService { return false } diff --git a/sentryflow/k8s/k8sHandler.go b/sentryflow/k8s/k8sHandler.go index 0b64aaa..11b9604 100644 --- a/sentryflow/k8s/k8sHandler.go +++ b/sentryflow/k8s/k8sHandler.go @@ -5,11 +5,12 @@ package k8s import ( "context" "errors" - "k8s.io/apimachinery/pkg/util/json" "log" "sync" "time" + "k8s.io/apimachinery/pkg/util/json" + "github.com/5gsec/SentryFlow/types" corev1 "k8s.io/api/core/v1" diff --git a/sentryflow/processor/apiAnalyzer.go b/sentryflow/processor/apiAnalyzer.go index 7971380..1439885 100644 --- a/sentryflow/processor/apiAnalyzer.go +++ b/sentryflow/processor/apiAnalyzer.go @@ -10,7 +10,7 @@ import ( // == // -// APIA Local reference for API analyzer +// APIA Local reference for API Analyzer var APIA *Analyzer // init function @@ -20,20 +20,20 @@ func init() { // Analyzer Structure type Analyzer struct { + stopChan chan struct{} + apiLog chan string apiLogs []string - analyzerLock sync.Mutex - - stopChan chan struct{} + apiLogsLock sync.Mutex } // NewAPIAnalyzer Function func NewAPIAnalyzer() *Analyzer { ret := &Analyzer{ - apiLog: make(chan string), - apiLogs: []string{}, - analyzerLock: sync.Mutex{}, + apiLog: make(chan string), + apiLogs: []string{}, + apiLogsLock: sync.Mutex{}, } return ret } @@ -71,16 +71,16 @@ func analyzeAPIs(wg *sync.WaitGroup) { continue } - APIA.analyzerLock.Lock() + APIA.apiLogsLock.Lock() APIA.apiLogs = append(APIA.apiLogs, api) - + if len(APIA.apiLogs) > config.GlobalConfig.AIEngineBatchSize { InsertAPILogsAI(APIA.apiLogs) APIA.apiLogs = []string{} } - APIA.analyzerLock.Unlock() + APIA.apiLogsLock.Unlock() case <-APIA.stopChan: wg.Done() return @@ -89,5 +89,3 @@ func analyzeAPIs(wg *sync.WaitGroup) { } // == // - -// == // diff --git a/sentryflow/processor/apiClassifier.go b/sentryflow/processor/apiClassifier.go index a361a4a..f944fc3 100644 --- a/sentryflow/processor/apiClassifier.go +++ b/sentryflow/processor/apiClassifier.go @@ -15,12 +15,11 @@ import ( "google.golang.org/grpc" ) -// AIH Local reference for AI handler server +// AH Local reference for AI Handler var AH *AIHandler // AIHandler Structure type AIHandler struct { - error chan error stopChan chan struct{} aggregatedLogs chan []*protobuf.APILog @@ -36,7 +35,6 @@ type streamInform struct { // init Function func init() { - // Construct address and start listening AH = NewAIHandler() } @@ -48,10 +46,11 @@ func NewAIHandler() *AIHandler { aggregatedLogs: make(chan []*protobuf.APILog), APIs: make(chan []string), } + return ah } -// initHandler Function +// StartAPIClassifier Function func StartAPIClassifier(wg *sync.WaitGroup) bool { AIEngineService := fmt.Sprintf("%s:%s", config.GlobalConfig.AIEngineService, config.GlobalConfig.AIEngineServicePort) @@ -83,7 +82,7 @@ func StartAPIClassifier(wg *sync.WaitGroup) bool { return true } -// InsertAPILog function +// InsertAPILogsAI function func InsertAPILogsAI(APIs []string) { AH.APIs <- APIs } diff --git a/sentryflow/processor/logProcessor.go b/sentryflow/processor/logProcessor.go index 782ebb8..ccbdaae 100644 --- a/sentryflow/processor/logProcessor.go +++ b/sentryflow/processor/logProcessor.go @@ -83,7 +83,7 @@ func InsertAPILog(data interface{}) { LogH.apiLogChan <- data } -// ProcessLogs Function +// ProcessAPILogs Function func ProcessAPILogs(wg *sync.WaitGroup) { wg.Add(1)