-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lambda-promtail: Add support for WAF logs in S3 #10416
Merged
cstyan
merged 11 commits into
grafana:main
from
lpugoy:lambda_promtail_add_support_waf_logs
Sep 6, 2023
Merged
Changes from 9 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
77011d1
lambda-promtail: Add support for WAF logs in S3
lpugoy fa1e2e3
Merge branch 'main' into lambda_promtail_add_support_waf_logs
lpugoy aae7df4
lambda-promtail: Warn on unknown timestamp type
lpugoy 53c225a
lambda-promtail: Change Unix time parsing
lpugoy 41858cf
Merge branch 'main' into lambda_promtail_add_support_waf_logs
lpugoy f113dff
Merge branch 'main' into lambda_promtail_add_support_waf_logs
lpugoy 22e06c9
Merge branch 'main' into lambda_promtail_add_support_waf_logs
lpugoy 7401d1e
Fix changelog entry
lpugoy 679c3ba
Merge branch 'main' into lambda_promtail_add_support_waf_logs
lpugoy 69deff9
lambda-promtail: Fix typo
lpugoy f96be00
Merge branch 'main' into lambda_promtail_add_support_waf_logs
lpugoy File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"io" | ||
"os" | ||
|
@@ -9,9 +10,9 @@ import ( | |
"time" | ||
|
||
"github.com/aws/aws-lambda-go/events" | ||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/go-kit/log" | ||
"github.com/grafana/loki/pkg/logproto" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func Test_getLabels(t *testing.T) { | ||
|
@@ -257,6 +258,41 @@ func Test_getLabels(t *testing.T) { | |
}, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "s3_waf", | ||
args: args{ | ||
record: events.S3EventRecord{ | ||
AWSRegion: "us-east-1", | ||
S3: events.S3Entity{ | ||
Bucket: events.S3Bucket{ | ||
Name: "waf_logs_test", | ||
OwnerIdentity: events.S3UserIdentity{ | ||
PrincipalID: "test", | ||
}, | ||
}, | ||
Object: events.S3Object{ | ||
Key: "prefix/AWSLogs/11111111111/WAFLogs/us-east-1/TEST-WEBACL/2021/10/28/19/50/11111111111_waflogs_us-east-1_TEST-WEBACL_20211028T1950Z_e0ca43b5.log.gz", | ||
}, | ||
}, | ||
}, | ||
}, | ||
want: map[string]string{ | ||
"account_id": "11111111111", | ||
"bucket_owner": "test", | ||
"bucket_region": "us-east-1", | ||
"bucket": "waf_logs_test", | ||
"day": "28", | ||
"hour": "19", | ||
"key": "prefix/AWSLogs/11111111111/WAFLogs/us-east-1/TEST-WEBACL/2021/10/28/19/50/11111111111_waflogs_us-east-1_TEST-WEBACL_20211028T1950Z_e0ca43b5.log.gz", | ||
"minute": "50", | ||
"month": "10", | ||
"region": "us-east-1", | ||
"src": "TEST-WEBACL", | ||
"type": WAF_LOG_TYPE, | ||
"year": "2021", | ||
}, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "missing_type", | ||
args: args{ | ||
|
@@ -313,6 +349,7 @@ func Test_parseS3Log(t *testing.T) { | |
expectedLen int | ||
expectedStream string | ||
expectedTimestamps []time.Time | ||
expectedLog string | ||
}{ | ||
{ | ||
name: "vpcflowlogs", | ||
|
@@ -443,6 +480,27 @@ func Test_parseS3Log(t *testing.T) { | |
}, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "waflogs", | ||
args: args{ | ||
batchSize: 131072, // Set large enough we don't try and send to promtail | ||
filename: "../testdata/waflog.log.gz", | ||
b: &batch{ | ||
streams: map[string]*logproto.Stream{}, | ||
}, | ||
labels: map[string]string{ | ||
"account_id": "11111111111", | ||
"src": "TEST-WEBACL", | ||
"type": WAF_LOG_TYPE, | ||
}, | ||
}, | ||
expectedLen: 1, | ||
expectedStream: `{__aws_log_type="s3_waf", __aws_s3_waf="TEST-WEBACL", __aws_s3_waf_owner="11111111111"}`, | ||
expectedTimestamps: []time.Time{ | ||
time.Date(2023, time.August, 31, 4, 57, 42, 729000000, time.UTC), | ||
}, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "missing_parser", | ||
args: args{ | ||
|
@@ -463,6 +521,31 @@ func Test_parseS3Log(t *testing.T) { | |
expectedStream: "", | ||
wantErr: true, | ||
}, | ||
{ | ||
name: "no_timestamp_type", | ||
args: args{ | ||
batchSize: 131072, // Set large enough we don't try and send to promtail | ||
filename: "../testdata/waflog.log.gz", | ||
b: &batch{ | ||
streams: map[string]*logproto.Stream{}, | ||
}, | ||
labels: map[string]string{ | ||
"account_id": "11111111111", | ||
"src": "TEST-WEBACL", | ||
"type": "no_type", | ||
}, | ||
}, | ||
expectedLen: 1, | ||
expectedStream: `{__aws_log_type="s3_waf", __aws_s3_waf="TEST-WEBACL", __aws_s3_waf_owner="11111111111"}`, | ||
expectedLog: `level=warn msg="timestamp type of no_type parser unknown, using current time"` + "\n", | ||
wantErr: false, | ||
}, | ||
} | ||
parsers["no_type"] = parserConfig{ | ||
logTypeLabel: "s3_waf", | ||
filenameRegex: wafFilenameRegex, | ||
ownerLabelKey: "account_id", | ||
timestampRegex: wafTimestampRegex, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
|
@@ -472,7 +555,9 @@ func Test_parseS3Log(t *testing.T) { | |
if err != nil { | ||
t.Errorf("parseS3Log() failed to open test file: %s - %v", tt.args.filename, err) | ||
} | ||
if err := parseS3Log(context.Background(), tt.args.b, tt.args.labels, tt.args.obj); (err != nil) != tt.wantErr { | ||
buf := &bytes.Buffer{} | ||
log := log.NewLogfmtLogger(buf) | ||
if err := parseS3Log(context.Background(), tt.args.b, tt.args.labels, tt.args.obj, &log); (err != nil) != tt.wantErr { | ||
t.Errorf("parseS3Log() error = %v, wantErr %v", err, tt.wantErr) | ||
} | ||
require.Len(t, tt.args.b.streams, tt.expectedLen) | ||
|
@@ -486,6 +571,7 @@ func Test_parseS3Log(t *testing.T) { | |
require.Equal(t, tt.expectedTimestamps[i], entry.Timestamp) | ||
} | ||
} | ||
require.Equal(t, tt.expectedLog, buf.String()) | ||
} | ||
}) | ||
} | ||
|
@@ -595,3 +681,72 @@ func TestProcessSQSEvent(t *testing.T) { | |
require.Nil(t, err) | ||
require.True(t, handlerCalled) | ||
} | ||
|
||
func TestGetUnixSecNsec(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this test needs a case for the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This tests |
||
type args struct { | ||
s string | ||
} | ||
tests := []struct { | ||
name string | ||
args args | ||
wantErr bool | ||
expectedSec int64 | ||
expectedNsec int64 | ||
}{ | ||
{ | ||
name: "timestamp_in_seconds", | ||
args: args{ | ||
s: "1234567890", | ||
}, | ||
expectedSec: 1234567890, | ||
expectedNsec: 0, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "timestamp_in_milliseconds", | ||
args: args{ | ||
s: "1234567890123", | ||
}, | ||
expectedSec: 1234567890, | ||
expectedNsec: 123000000, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "timestamp_in_microseconds", | ||
args: args{ | ||
s: "1234567890123456", | ||
}, | ||
expectedSec: 1234567890, | ||
expectedNsec: 123456000, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "timestamp_in_nanoseconds", | ||
args: args{ | ||
s: "1234567890123456789", | ||
}, | ||
expectedSec: 1234567890, | ||
expectedNsec: 123456789, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "strconv_error", | ||
args: args{ | ||
s: "string", | ||
}, | ||
expectedSec: 0, | ||
expectedNsec: 0, | ||
wantErr: true, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
sec, nsec, err := getUnixSecNsec(tt.args.s) | ||
if (err != nil) != tt.wantErr { | ||
t.Errorf("toMicroseconds() error = %v, wantErr %v", err, tt.wantErr) | ||
} | ||
require.Equal(t, tt.expectedSec, sec) | ||
require.Equal(t, tt.expectedNsec, nsec) | ||
}) | ||
} | ||
} |
Binary file not shown.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you want to set an actual value for
err
here? otherwise it has the nil value fromstrconv.ParseInt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes,
err
would be nil iffractionalSec
is 0. There would only be an error during parsing,fractionalSec
being 0 just means that the Unix time only has seconds resolution. It is not an error.