Skip to content

Commit 980d073

Browse files
feat: add NLB log support (#72)
* feat: add NLB log support Signed-off-by: Kavindu Dodanduwa <[email protected]> * Apply suggestion from @Copilot Co-authored-by: Copilot <[email protected]> * Apply suggestion from @Copilot Co-authored-by: Copilot <[email protected]> * review: field name Signed-off-by: Kavindu Dodanduwa <[email protected]> * chore: improve readme Signed-off-by: Kavindu Dodanduwa <[email protected]> * Update generators/nlb.go Co-authored-by: Copilot <[email protected]> --------- Signed-off-by: Kavindu Dodanduwa <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent 4664bc1 commit 980d073

File tree

7 files changed

+144
-5
lines changed

7 files changed

+144
-5
lines changed

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Data Generator
1+
# Synthetic Data Generator
22

3-
A simple data generator with export capability to various destinations
3+
A flexible synthetic data generator in Go, designed to produce realistic logs and metrics for testing and development.
44

55
## Quick Start
66

@@ -25,7 +25,7 @@ Given below are supported input types and their related environment variable ove
2525

2626
| YAML Property | Environment Variable | Description |
2727
|-------------------|-----------------------------|------------------------------------------------------------------------------------------------------------------|
28-
| `type` | `ENV_INPUT_TYPE` | Specifies the input data type (e.g., `LOGS`, `METRICS`, `ALB`, `VPC`, `CLOUDTRAIL`, `WAF`). |
28+
| `type` | `ENV_INPUT_TYPE` | Specifies the input data type (e.g., `LOGS`, `METRICS`, `ALB`, `NLB`, `VPC`, `CLOUDTRAIL`, `WAF`). |
2929
| `delay` | `ENV_INPUT_DELAY` | Delay between a data point. Accepts value in format like `5s` (5 seconds), `10ms` (10 milliseconds). |
3030
| `batching` | `ENV_INPUT_BATCHING` | Set time delay between data batches. Accepts a time value similar to delay. Default is set to `0` (no batching). |
3131
| `max_batch_size` | `ENV_INPUT_MAX_BATCH_SIZE` | Set maximum byte size of a batch. Default is to ignore (no max size). |
@@ -36,7 +36,8 @@ Note about input `type`,
3636

3737
- `LOGS` : ECS (Elastic Common Schema) formatted logs based on zap
3838
- `METRICS`: Generate metrics similar to a CloudWatch metrics entry
39-
- `ALB` : Generate AWS ALB formatted log with some random content
39+
- `ALB` : Generate AWS ALB formatted logs with some random content
40+
- `NLB` : Generate AWS NLB formatted logs with some random content
4041
- `VPC`: Generate AWS VPC formatted logs with randomized content
4142
- `CLOUDTRAIL`: Generate AWS CloudTrail formatted logs with randomized content. Data is generated for AWS S3 Data Event.
4243
- `WAF`: Generate AWS WAF formatted logs with randomized content
File renamed without changes.

generators/generator.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const (
1313
logs = "LOGS"
1414
metrics = "METRICS"
1515
alb = "ALB"
16+
nlb = "NLB"
1617
vpc = "VPC"
1718
waf = "WAF"
1819
CloudTrail = "CLOUDTRAIL"
@@ -33,6 +34,8 @@ func GeneratorFor(config *conf.Config) (*Generator, error) {
3334
return newGenerator(config.Input, NewMetricGenerator()), nil
3435
case alb:
3536
return newGenerator(config.Input, NewALBGen()), nil
37+
case nlb:
38+
return newGenerator(config.Input, NewNLBGen()), nil
3639
case vpc:
3740
return newGenerator(config.Input, newVPCGen()), nil
3841
case waf:

generators/nlb.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package generators
2+
3+
import (
4+
"fmt"
5+
"math/rand"
6+
)
7+
8+
type NLBgen struct {
9+
buf trackedBuffer
10+
}
11+
12+
func NewNLBGen() *NLBgen {
13+
return &NLBgen{
14+
buf: newTrackedBuffer(),
15+
}
16+
}
17+
18+
func (a *NLBgen) Generate() (int64, error) {
19+
customizer := nlbCustomizer{
20+
time: iso8601Now(),
21+
name: fmt.Sprintf("net/my-nlb/%s", randomID()),
22+
elbID: randomID(),
23+
clientIPPort: fmt.Sprintf("%s:%d", randomIP(), randomPort()),
24+
destinationIPPort: fmt.Sprintf("%s:%d", randomIP(), randomPort()),
25+
conMs: rand.Intn(1000),
26+
tlsHSMs: rand.Intn(1000),
27+
receivedBytes: randomBytesSize(),
28+
sentBytes: randomBytesSize(),
29+
tlsAlert: "-",
30+
certARN: randomCertArn(),
31+
cipher: randomSSLCipher(),
32+
protocol: sslProtocol(),
33+
domain: randomDomain(),
34+
feProtocol: "-",
35+
beProtocol: "-",
36+
alpnList: "-",
37+
creationTime: iso8601Now(),
38+
}
39+
40+
err := a.buf.write([]byte(buildNLBLogLine(customizer)))
41+
if err != nil {
42+
return 0, err
43+
}
44+
45+
return a.buf.size(), err
46+
}
47+
48+
func (a *NLBgen) GetAndReset() []byte {
49+
return a.buf.getAndReset()
50+
}
51+
52+
// helpers
53+
54+
type nlbCustomizer struct {
55+
time string
56+
name string
57+
elbID string
58+
clientIPPort string
59+
destinationIPPort string
60+
conMs int
61+
tlsHSMs int
62+
receivedBytes int
63+
sentBytes int
64+
tlsAlert string
65+
certARN string
66+
cipher string
67+
protocol string
68+
domain string
69+
feProtocol string
70+
beProtocol string
71+
alpnList string
72+
creationTime string
73+
}
74+
75+
func buildNLBLogLine(input nlbCustomizer) string {
76+
// Construct the log line
77+
log := fmt.Sprintf(
78+
"%s %s %s %s %s %s %s %d %d %d %d %s %s %s %s %s %s %s %s %s %s %s\n",
79+
"tls", "2.0", input.time, input.name, input.elbID, input.clientIPPort, input.destinationIPPort, input.conMs,
80+
input.tlsHSMs, input.receivedBytes, input.sentBytes,
81+
input.tlsAlert, input.certARN, "-", // Placeholder for future fields
82+
input.cipher, input.protocol, "-", // Placeholder for future fields
83+
input.domain,
84+
input.feProtocol, input.beProtocol, input.alpnList, input.creationTime,
85+
)
86+
87+
return log
88+
}

generators/nlb_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package generators
2+
3+
import (
4+
"github.com/stretchr/testify/require"
5+
"strings"
6+
"testing"
7+
)
8+
9+
// refer http example of https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-access-logs.html#access-log-entry-format
10+
const upstreamNLB = `tls 2.0 2020-04-01T08:51:42 net/my-network-loadbalancer/c6e77e28c25b2234 g3d4b5e8bb8464cd 72.21.218.154:51341 172.100.100.185:443 5 2 98 246 - arn:aws:acm:us-east-2:671290407336:certificate/2a108f19-aded-46b0-8493-c63eb1ef4a99 - ECDHE-RSA-AES128-SHA tlsv12 - my-network-loadbalancer-c6e77e28c25b2234.elb.us-east-2.amazonaws.com h2 h2 "h2","http/1.1" 2020-04-01T08:51:20`
11+
12+
func Test_buildNLB(t *testing.T) {
13+
t.Run("Validate AWS documented HTTP NLB line", func(t *testing.T) {
14+
line := buildNLBLogLine(nlbCustomizer{
15+
time: "2020-04-01T08:51:42",
16+
name: "net/my-network-loadbalancer/c6e77e28c25b2234",
17+
elbID: "g3d4b5e8bb8464cd",
18+
clientIPPort: "72.21.218.154:51341",
19+
destinationIPPort: "172.100.100.185:443",
20+
conMs: 5,
21+
tlsHSMs: 2,
22+
receivedBytes: 98,
23+
sentBytes: 246,
24+
tlsAlert: "-",
25+
certARN: "arn:aws:acm:us-east-2:671290407336:certificate/2a108f19-aded-46b0-8493-c63eb1ef4a99",
26+
cipher: "ECDHE-RSA-AES128-SHA",
27+
protocol: "tlsv12",
28+
domain: "my-network-loadbalancer-c6e77e28c25b2234.elb.us-east-2.amazonaws.com",
29+
feProtocol: "h2",
30+
beProtocol: "h2",
31+
alpnList: `"h2","http/1.1"`,
32+
creationTime: "2020-04-01T08:51:20",
33+
})
34+
35+
require.Equal(t, upstreamNLB, strings.TrimSpace(line))
36+
})
37+
}

generators/utils.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ var tt = true
1616

1717
var contentTypes = []string{"text/html", "application/json", "text/plain", "application/xml"}
1818
var countryCodes = []string{"US", "GB", "DE", "FR", "IN", "CN", "JP", "AU", "CA", "BR"}
19-
var sampleDomains = []string{"example.com", "test.com", "sample.org", "demo.net"}
19+
var randomIDs = []string{"id123", "id456", "id789", "id101", "id112", "id131"}
2020
var httpMethods = []string{"GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"}
2121
var httpSchema = []string{"http", "https"}
2222
var httpSourceIDs = []string{"E2A1BCD34FGH56", "E3B2CDE45GHI67", "E4C3DEF56HIJ78", "E5D4EFG67IJK89"}
@@ -26,6 +26,7 @@ var randomPhrases = []string{"some random phrase", "another random phrase", "yet
2626
var regions = []string{"us-east-1", "us-west-1", "us-west-2", "eu-west-1", "eu-central-1"}
2727
var s3EventNames = []string{"PutObject", "GetObject", "DeleteObject", "ListObjects"}
2828
var sampleAccountIDs = []string{"123456789012", "987654321098", "111122223333", "444455556666", "777788889999"}
29+
var sampleDomains = []string{"example.com", "test.com", "sample.org", "demo.net"}
2930
var samplePrincipalIDs = []string{"AID1234567890", "AID0987654321", "AID1111222233", "AID7777888899"}
3031
var sampleRuleIDs = []string{"rule-1", "rule-2", "rule-3", "rule-4", "rule-5"}
3132
var sslCiphers = []string{"ECDHE-RSA-AES128-GCM-SHA256", "ECDHE-RSA-AES256-GCM-SHA384", "AES128-GCM-SHA256"}
@@ -38,6 +39,7 @@ var vpcActions = []string{"ACCEPT", "REJECT"}
3839
var wafActions = []string{"ALLOW", "BLOCK", "COUNT"}
3940
var wafRuleTypes = []string{"REGULAR", "RATE_BASED", "GROUP"}
4041
var wafSampleHTTPSourceNames = []string{"ALB", "CloudFront", "API Gateway"}
42+
var certARN = []string{"arn:aws:acm:us-east-1:123456789012:certificate/1", "arn:aws:acm:us-east-1:123456789012:certificate/2", "arn:aws:acm:us-east-1:123456789012:certificate/3"}
4143

4244
// ipPrefix contains example public IP address prefixes, representing geo-distributed or commonly used public IP ranges.
4345
var ipPrefix = []int{1, 8, 31, 41, 91, 123, 179, 201, 210, 250}
@@ -59,6 +61,14 @@ func randomProcessingTime() float32 {
5961
return (0.5 + rand.Float32()*1000) / 1000
6062
}
6163

64+
func randomID() string {
65+
return randomIDs[rand.Intn(len(randomIDs))]
66+
}
67+
68+
func randomCertArn() string {
69+
return certARN[rand.Intn(len(certARN))]
70+
}
71+
6272
func randomStatus() string {
6373
return statuses[rand.Intn(len(statuses))]
6474
}

0 commit comments

Comments
 (0)