Skip to content

Commit

Permalink
implement proof writer
Browse files Browse the repository at this point in the history
  • Loading branch information
solnicki committed Nov 19, 2024
1 parent 0f9a78a commit aed9920
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 50 deletions.
9 changes: 7 additions & 2 deletions cmd/logveil/logveil.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/logmanager-oss/logveil/internal/anonymizer"
"github.com/logmanager-oss/logveil/internal/config"
"github.com/logmanager-oss/logveil/internal/files"
"github.com/logmanager-oss/logveil/internal/proof"
"github.com/logmanager-oss/logveil/internal/reader"
"github.com/logmanager-oss/logveil/internal/writer"
)
Expand All @@ -20,7 +21,7 @@ func Start() {
config := &config.Config{}
config.LoadAndValidate()

if *config.IsVerbose {
if config.IsVerbose {
slog.SetLogLoggerLevel(slog.LevelDebug)
}

Expand All @@ -35,7 +36,11 @@ func Start() {
if err != nil {
return
}
anonymizerDoer, err := anonymizer.CreateAnonymizer(config)
proofWriter, err := proof.CreateProofWriter(config, filesHandler)
if err != nil {
return
}
anonymizerDoer, err := anonymizer.CreateAnonymizer(config, proofWriter)
if err != nil {
return
}
Expand Down
17 changes: 12 additions & 5 deletions internal/anonymizer/anonymizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,33 @@ import (

"github.com/logmanager-oss/logveil/internal/config"
"github.com/logmanager-oss/logveil/internal/loader"
"github.com/logmanager-oss/logveil/internal/proof"
"golang.org/x/exp/rand"
)

// Anonymizer represents an object responsible for anonymizing indivisual log lines feed to it. It contains anonymization data which will be used to anonymize input and a random number generator funtion used to select values from anonymization data.
type Anonymizer struct {
anonData map[string][]string
randFunc func(int) int
anonData map[string][]string
randFunc func(int) int
proofWriter *proof.ProofWriter
}

func CreateAnonymizer(config *config.Config) (*Anonymizer, error) {
func CreateAnonymizer(config *config.Config, proofWriter *proof.ProofWriter) (*Anonymizer, error) {
anonymizingData, err := loader.Load(config.AnonymizationDataPath)
if err != nil {
return nil, fmt.Errorf("loading anonymizing data from dir %s: %v", config.AnonymizationDataPath, err)
}

return &Anonymizer{
anonData: anonymizingData,
randFunc: rand.Intn,
anonData: anonymizingData,
randFunc: rand.Intn,
proofWriter: proofWriter,
}, nil
}

func (an *Anonymizer) Anonymize(logLine map[string]string) string {
defer an.proofWriter.Flush()

for field, value := range logLine {
if field == "raw" {
continue
Expand All @@ -41,6 +46,8 @@ func (an *Anonymizer) Anonymize(logLine map[string]string) string {
if anonValues, exists := an.anonData[field]; exists {
newAnonValue := anonValues[an.randFunc(len(anonValues))]

an.proofWriter.Write(value, newAnonValue)

slog.Debug(fmt.Sprintf("Replacing the values for field %s. From %s to %s.\n", field, value, newAnonValue))

logLine["raw"] = strings.Replace(logLine["raw"], value, newAnonValue, -1)
Expand Down
3 changes: 2 additions & 1 deletion internal/anonymizer/anonymizer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"testing"

"github.com/logmanager-oss/logveil/internal/config"
"github.com/logmanager-oss/logveil/internal/proof"
"github.com/stretchr/testify/assert"
)

Expand All @@ -24,7 +25,7 @@ func TestAnonimizer_AnonymizeData(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
anonymizer, err := CreateAnonymizer(&config.Config{AnonymizationDataPath: tt.anonymizingDataDir})
anonymizer, err := CreateAnonymizer(&config.Config{AnonymizationDataPath: tt.anonymizingDataDir}, &proof.ProofWriter{IsEnabled: false})
if err != nil {
t.Fatal(err)
}
Expand Down
10 changes: 6 additions & 4 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ type Config struct {
AnonymizationDataPath string
InputPath string
OutputPath string
IsVerbose *bool
IsLmExport *bool
IsVerbose bool
IsLmExport bool
IsProofWriter bool
}

// LoadAndValidate loads values from user supplied input into Config struct and validates them
Expand All @@ -21,8 +22,9 @@ func (c *Config) LoadAndValidate() {

flag.Func("o", "Path to output file (default: Stdout)", validateOutput(c.OutputPath))

c.IsVerbose = flag.Bool("v", false, "Enable verbose logging (default: Disabled)")
c.IsLmExport = flag.Bool("e", false, "Change input file type to LM export (default: LM Backup)")
flag.BoolVar(&c.IsVerbose, "v", false, "Enable verbose logging (default: Disabled)")
flag.BoolVar(&c.IsLmExport, "e", false, "Change input file type to LM export (default: LM Backup)")
flag.BoolVar(&c.IsProofWriter, "p", true, "Disable proof wrtier (default: Enabled)")

flag.Parse()
}
68 changes: 68 additions & 0 deletions internal/proof/proof.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package proof

import (
"bufio"
"encoding/json"
"fmt"
"log/slog"
"os"

"github.com/logmanager-oss/logveil/internal/config"
"github.com/logmanager-oss/logveil/internal/files"
)

type ProofWriter struct {
IsEnabled bool
writer *bufio.Writer
file *os.File
}

func CreateProofWriter(config *config.Config, openFiles *files.FilesHandler) (*ProofWriter, error) {
if config.IsProofWriter {
file, err := os.Create("proof.json")
if err != nil {
return nil, fmt.Errorf("creating/opening proof file: %v", err)
}
openFiles.Add(file)

return &ProofWriter{
IsEnabled: true,
writer: bufio.NewWriter(file),
file: file,
}, nil
}

return &ProofWriter{IsEnabled: false}, nil
}

func (p *ProofWriter) Write(originalValue string, maskedValue string) {
if !p.IsEnabled {
return
}

proof := struct {
OriginalValue string `json:"original"`
MaskedValue string `json:"new"`
}{
OriginalValue: originalValue,
MaskedValue: maskedValue,
}

bytes, err := json.Marshal(proof)
if err != nil {
slog.Error("marshalling anonymisation proof", "error", err)
}

_, err = fmt.Fprintf(p.writer, "%s\n", bytes)
if err != nil {
slog.Error("writing anonymisation proof", "error", err)
}
}

func (p *ProofWriter) Flush() {
if !p.IsEnabled {
return
}

p.writer.Flush()
}
68 changes: 68 additions & 0 deletions internal/proof/proof_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package proof

import (
"bytes"
"io"
"os"
"testing"

"github.com/logmanager-oss/logveil/internal/config"
"github.com/logmanager-oss/logveil/internal/files"
"github.com/stretchr/testify/assert"
)

func TestProof_Write(t *testing.T) {
tests := []struct {
name string
isProofWriter bool
originalValue string
maskedValue string
expectedOutput string
}{
{
name: "Test case 1: write proof",
isProofWriter: true,
originalValue: "test",
maskedValue: "masked",
expectedOutput: "{\"original\":\"test\",\"new\":\"masked\"}\n",
},
{
name: "Test case 2: proof writer disabled",
isProofWriter: false,
originalValue: "test",
maskedValue: "masked",
expectedOutput: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
filesHandler := &files.FilesHandler{}
defer filesHandler.Close()

p, err := CreateProofWriter(&config.Config{IsProofWriter: tt.isProofWriter}, filesHandler)
if err != nil {
t.Fatal(err)
}

p.Write(tt.originalValue, tt.maskedValue)
p.Flush()

file, err := os.OpenFile("proof.json", os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
t.Fatal(err)
}

buf := bytes.NewBuffer(nil)
_, err = io.Copy(buf, file)
if err != nil {
t.Fatal(err)
}

file.Close()

assert.Equal(t, tt.expectedOutput, buf.String())

os.Remove("proof.json")
})
}
}
6 changes: 3 additions & 3 deletions internal/reader/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@ import (
"os"

"github.com/logmanager-oss/logveil/internal/config"
file "github.com/logmanager-oss/logveil/internal/files"
"github.com/logmanager-oss/logveil/internal/files"
)

type InputReader interface {
ReadLine() (map[string]string, error)
Close() error
}

func CreateInputReader(config *config.Config, openFiles *file.FilesHandler) (InputReader, error) {
func CreateInputReader(config *config.Config, openFiles *files.FilesHandler) (InputReader, error) {
inputFile, err := os.Open(config.InputPath)
if err != nil {
return nil, fmt.Errorf("opening input file for reading: %v", err)
}
openFiles.Add(inputFile)

if *config.IsLmExport {
if config.IsLmExport {
inputReader, err := NewLmExportReader(inputFile)
if err != nil {
return nil, fmt.Errorf("initializin LM Export reader: %v", err)
Expand Down
8 changes: 4 additions & 4 deletions internal/writer/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import (
"os"

"github.com/logmanager-oss/logveil/internal/config"
file "github.com/logmanager-oss/logveil/internal/files"
"github.com/logmanager-oss/logveil/internal/files"
)

func CreateOutputWriter(configFile *config.Config, openFiles *file.FilesHandler) (*bufio.Writer, error) {
func CreateOutputWriter(config *config.Config, openFiles *files.FilesHandler) (*bufio.Writer, error) {
var outputFile *os.File
if configFile.OutputPath != "" {
outputFile, err := os.Create(configFile.OutputPath)
if config.OutputPath != "" {
outputFile, err := os.Create(config.OutputPath)
if err != nil {
return nil, fmt.Errorf("opening output file for writing: %v", err)
}
Expand Down
Loading

0 comments on commit aed9920

Please sign in to comment.