From b87b663b9b88f4e1dbd5eca3bc4390fa2d75d748 Mon Sep 17 00:00:00 2001 From: Andrew Kroh Date: Wed, 20 Dec 2017 13:15:02 -0500 Subject: [PATCH] Add Digest type implementing TextMarshaler This adds `type Digest []byte` for representing the result of a hash function. This new type implements the Stringer and TextMarshaler interfaces so that the digest value is represented as a hexadecimal string. --- auditbeat/module/file_integrity/action.go | 3 +++ auditbeat/module/file_integrity/event.go | 27 +++++++++++++++---- auditbeat/module/file_integrity/event_test.go | 8 +++--- .../module/file_integrity/flatbuffers.go | 6 ++--- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/auditbeat/module/file_integrity/action.go b/auditbeat/module/file_integrity/action.go index 2420d2833753..0dae5b7f25ff 100644 --- a/auditbeat/module/file_integrity/action.go +++ b/auditbeat/module/file_integrity/action.go @@ -83,6 +83,9 @@ func (action Action) String() string { return strings.Join(list, "|") } +// MarshalText marshals the Action to a textual representation of itself. +func (action Action) MarshalText() ([]byte, error) { return []byte(action.String()), nil } + func resolveActionOrder(action Action, existedBefore, existsNow bool) ActionArray { if action == None { return nil diff --git a/auditbeat/module/file_integrity/event.go b/auditbeat/module/file_integrity/event.go index 888664f5f099..88aa36130034 100644 --- a/auditbeat/module/file_integrity/event.go +++ b/auditbeat/module/file_integrity/event.go @@ -36,6 +36,9 @@ func (s Source) String() string { return "unknown" } +// MarshalText marshals the Source to a textual representation of itself. +func (s Source) MarshalText() ([]byte, error) { return []byte(s.String()), nil } + const ( // SourceScan identifies events triggerd by a file system scan. SourceScan Source = iota @@ -59,6 +62,9 @@ func (t Type) String() string { return "unknown" } +// MarshalText marshals the Type to a textual representation of itself. +func (t Type) MarshalText() ([]byte, error) { return []byte(t.String()), nil } + // Enum of possible file.Types. const ( UnknownType Type = iota // Typically seen in deleted notifications where the object is gone. @@ -73,6 +79,17 @@ var typeNames = map[Type]string{ SymlinkType: "symlink", } +// Digest is a output of a hash function. +type Digest []byte + +// String returns the digest value in lower-case hexadecimal form. +func (d Digest) String() string { + return hex.EncodeToString(d) +} + +// MarshalText encodes the digest to a hexadecimal representation of itself. +func (d Digest) MarshalText() ([]byte, error) { return []byte(d.String()), nil } + // Event describe the filesystem change and includes metadata about the file. type Event struct { Timestamp time.Time // Time of event. @@ -81,7 +98,7 @@ type Event struct { Info *Metadata // File metadata (if the file exists). Source Source // Source of the event. Action Action // Action (like created, updated). - Hashes map[HashType][]byte // File hashes. + Hashes map[HashType]Digest // File hashes. // Metadata rtt time.Duration // Time taken to collect the info. @@ -240,8 +257,8 @@ func buildMetricbeatEvent(e *Event, existedBefore bool) mb.Event { } } - for hashType, hash := range e.Hashes { - m[string(hashType)] = hex.EncodeToString(hash) + for hashType, digest := range e.Hashes { + m[string(hashType)] = digest } out := mb.Event{ @@ -319,7 +336,7 @@ func diffEvents(old, new *Event) (Action, bool) { return result, result != None } -func hashFile(name string, hashType ...HashType) (map[HashType][]byte, error) { +func hashFile(name string, hashType ...HashType) (map[HashType]Digest, error) { if len(hashType) == 0 { return nil, nil } @@ -376,7 +393,7 @@ func hashFile(name string, hashType ...HashType) (map[HashType][]byte, error) { return nil, errors.Wrap(err, "failed to calculate file hashes") } - nameToHash := make(map[HashType][]byte, len(hashes)) + nameToHash := make(map[HashType]Digest, len(hashes)) for i, h := range hashes { nameToHash[hashType[i]] = h.Sum(nil) } diff --git a/auditbeat/module/file_integrity/event_test.go b/auditbeat/module/file_integrity/event_test.go index 4f49e67add45..4c6a2e8851c8 100644 --- a/auditbeat/module/file_integrity/event_test.go +++ b/auditbeat/module/file_integrity/event_test.go @@ -31,7 +31,7 @@ func testEvent() *Event { MTime: testEventTime, SetGID: true, }, - Hashes: map[HashType][]byte{ + Hashes: map[HashType]Digest{ SHA1: mustDecodeHex("abcd"), SHA256: mustDecodeHex("1234"), }, @@ -109,7 +109,7 @@ func TestDiffEvents(t *testing.T) { t.Run("different hash values", func(t *testing.T) { e := testEvent() - e.Hashes = map[HashType][]byte{ + e.Hashes = map[HashType]Digest{ SHA1: mustDecodeHex("ef"), SHA256: mustDecodeHex("1234"), } @@ -121,7 +121,7 @@ func TestDiffEvents(t *testing.T) { t.Run("updated hashes and metadata", func(t *testing.T) { e := testEvent() - e.Hashes = map[HashType][]byte{ + e.Hashes = map[HashType]Digest{ SHA1: mustDecodeHex("ef"), SHA256: mustDecodeHex("1234"), } @@ -154,7 +154,7 @@ func TestDiffEvents(t *testing.T) { func TestHashFile(t *testing.T) { t.Run("valid hashes", func(t *testing.T) { // Computed externally. - expectedHashes := map[HashType][]byte{ + expectedHashes := map[HashType]Digest{ BLAKE2B_256: mustDecodeHex("0f0cc1f0ea4ef962d6a150ae0b77bc320b57ed24e1609b933fa2274484f59145"), BLAKE2B_384: mustDecodeHex("b819d90f648da6effff2393acb1884d2638642b3524c329832c073c9364149fcdedb522914ef9c2c92f007a42366139a"), BLAKE2B_512: mustDecodeHex("fc13029e8a5ce67ad5a70f0cc659a4b30df9d791b125835e434606c6127ee37ebbc8b216389682ddfa84380789db09f2535d2a9837454414ea3ff00ec0801150"), diff --git a/auditbeat/module/file_integrity/flatbuffers.go b/auditbeat/module/file_integrity/flatbuffers.go index f1322c57b917..bf6041b3815b 100644 --- a/auditbeat/module/file_integrity/flatbuffers.go +++ b/auditbeat/module/file_integrity/flatbuffers.go @@ -52,7 +52,7 @@ func fbEncodeEvent(b *flatbuffers.Builder, e *Event) []byte { return b.FinishedBytes() } -func fbWriteHash(b *flatbuffers.Builder, hashes map[HashType][]byte) flatbuffers.UOffsetT { +func fbWriteHash(b *flatbuffers.Builder, hashes map[HashType]Digest) flatbuffers.UOffsetT { if len(hashes) == 0 { return 0 } @@ -252,13 +252,13 @@ func fbDecodeMetadata(e *schema.Event) *Metadata { return rtn } -func fbDecodeHash(e *schema.Event) map[HashType][]byte { +func fbDecodeHash(e *schema.Event) map[HashType]Digest { hash := e.Hashes(nil) if hash == nil { return nil } - rtn := map[HashType][]byte{} + rtn := map[HashType]Digest{} for _, hashType := range validHashes { var length int var producer func(i int) int8