From d6eed3110f41dd3580c3750e9d9d577225a626fd Mon Sep 17 00:00:00 2001 From: steamvis Date: Sun, 22 May 2022 16:41:36 +0300 Subject: [PATCH 1/4] Add Same IP Addresses --- README.md | 23 ++++++++++++----------- main.go | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 9eb7fe9..5d18318 100644 --- a/README.md +++ b/README.md @@ -24,17 +24,18 @@ $ docker run -e "RATE=10" kscarlett/nginx-log-generator The following environment variables can be set to modify the output. -| Name | Default | Notes | -| ----------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | -| RATE | 1 | Logs to output per second. | -| IPV4_PERCENT | 100 | Percentage of IP addresses that will be IPv4. Change to 0 to only get IPv6. | -| STATUS_OK_PERCENT | 80 | _Roughly_ the percentage of `200` status codes. The rest will be randomised and may contain `200` as well. | -| PATH_MIN | 1 | Minimum elements to put in the request path. | -| PATH_MAX | 5 | Maximum elements to put in the request path. | -| GET_PERCENT | 60 | Percentage of requests that will be `GET` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | -| POST_PERCENT | 30 | Percentage of requests that will be `POST` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | -| PUT_PERCENT | 0 | Percentage of requests that will be `PUT` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | -| PATCH_PERCENT | 0 | Percentage of requests that will be `PATCH` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | +| Name | Default | Notes | +| ----------------- | ------- | ------------------------------------------------------------ | +| RATE | 1 | Logs to output per second. | +| IPV4_PERCENT | 100 | Percentage of IP addresses that will be IPv4. Change to 0 to only get IPv6. | +| SAME_IP_ADDRESSES | 0 | The number of identical IP addresses. If the value is 0, random IP addresses will be used | +| STATUS_OK_PERCENT | 80 | _Roughly_ the percentage of `200` status codes. The rest will be randomised and may contain `200` as well. | +| PATH_MIN | 1 | Minimum elements to put in the request path. | +| PATH_MAX | 5 | Maximum elements to put in the request path. | +| GET_PERCENT | 60 | Percentage of requests that will be `GET` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | +| POST_PERCENT | 30 | Percentage of requests that will be `POST` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | +| PUT_PERCENT | 0 | Percentage of requests that will be `PUT` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | +| PATCH_PERCENT | 0 | Percentage of requests that will be `PATCH` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | | DELETE_PERCENT | 0 | Percentage of requests that will be `DELETE` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | ## Note diff --git a/main.go b/main.go index cb6d227..6888f47 100644 --- a/main.go +++ b/main.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "math/rand" "strings" "time" @@ -12,6 +13,7 @@ import ( type config struct { Rate float32 `env:"RATE" envDefault:"1"` IPv4Percent int `env:"IPV4_PERCENT" envDefault:"100"` + SameIpAddresses int `env:"SAME_IP_ADDRESSES" envDefault: 0` StatusOkPercent int `env:"STATUS_OK_PERCENT" envDefault:"80"` PathMinLength int `env:"PATH_MIN" envDefault:"1"` PathMaxLength int `env:"PATH_MAX" envDefault:"5"` @@ -40,10 +42,21 @@ func main() { httpVersion = "HTTP/1.1" referrer = "-" + sameIpAddresses := []string{} + if cfg.SameIpAddresses > 0 { + for i := 0; i <= cfg.SameIpAddresses; i++ { + sameIpAddresses = append(sameIpAddresses, weightedIPVersion(cfg.IPv4Percent)) + } + } + for range ticker.C { timeLocal = time.Now() - ip = weightedIPVersion(cfg.IPv4Percent) + if len(sameIpAddresses) == 0 { + ip = weightedIPVersion(cfg.IPv4Percent) + } else { + ip = sameIpAddresses[rand.Intn(len(sameIpAddresses))] + } httpMethod = weightedHTTPMethod(cfg.PercentageGet, cfg.PercentagePost, cfg.PercentagePut, cfg.PercentagePatch, cfg.PercentageDelete) path = randomPath(cfg.PathMinLength, cfg.PathMaxLength) statusCode = weightedStatusCode(cfg.StatusOkPercent) From 464f51bc32613f8c38157bfa380bc61ca0979dd9 Mon Sep 17 00:00:00 2001 From: steamvis Date: Sun, 22 May 2022 16:54:24 +0300 Subject: [PATCH 2/4] Add Same IP Addresses --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 6888f47..7e31e33 100644 --- a/main.go +++ b/main.go @@ -13,7 +13,7 @@ import ( type config struct { Rate float32 `env:"RATE" envDefault:"1"` IPv4Percent int `env:"IPV4_PERCENT" envDefault:"100"` - SameIpAddresses int `env:"SAME_IP_ADDRESSES" envDefault: 0` + SameIpAddresses int `env:"SAME_IP_ADDRESSES" envDefault:"0"` StatusOkPercent int `env:"STATUS_OK_PERCENT" envDefault:"80"` PathMinLength int `env:"PATH_MIN" envDefault:"1"` PathMaxLength int `env:"PATH_MAX" envDefault:"5"` From b84403d4cb0db8612e31902059d1871e1699ab93 Mon Sep 17 00:00:00 2001 From: steamvis Date: Sat, 23 Jul 2022 12:03:39 +0300 Subject: [PATCH 3/4] Add option to write to file instead of stdout --- README.md | 32 +++++++++++++++++--------------- main.go | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 5d18318..e534e38 100644 --- a/README.md +++ b/README.md @@ -16,27 +16,29 @@ $ RATE=10 ./nginx-log-generator The reason this is an environment variable is so it's easier to run via Docker as well: ```sh -$ docker pull kscarlett/nginx-log-generator -$ docker run -e "RATE=10" kscarlett/nginx-log-generator +$ docker pull steamvis/nginx-log-generator +$ docker run -e "RATE=10" steamvis/nginx-log-generator ``` ### Configuration The following environment variables can be set to modify the output. -| Name | Default | Notes | -| ----------------- | ------- | ------------------------------------------------------------ | -| RATE | 1 | Logs to output per second. | -| IPV4_PERCENT | 100 | Percentage of IP addresses that will be IPv4. Change to 0 to only get IPv6. | -| SAME_IP_ADDRESSES | 0 | The number of identical IP addresses. If the value is 0, random IP addresses will be used | -| STATUS_OK_PERCENT | 80 | _Roughly_ the percentage of `200` status codes. The rest will be randomised and may contain `200` as well. | -| PATH_MIN | 1 | Minimum elements to put in the request path. | -| PATH_MAX | 5 | Maximum elements to put in the request path. | -| GET_PERCENT | 60 | Percentage of requests that will be `GET` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | -| POST_PERCENT | 30 | Percentage of requests that will be `POST` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | -| PUT_PERCENT | 0 | Percentage of requests that will be `PUT` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | -| PATCH_PERCENT | 0 | Percentage of requests that will be `PATCH` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | -| DELETE_PERCENT | 0 | Percentage of requests that will be `DELETE` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | +| Name | Default | Notes | +| ----------------- | -------- | ------------------------------------------------------------ | +| RATE | 1 | Logs to output per second. | +| IPV4_PERCENT | 100 | Percentage of IP addresses that will be IPv4. Change to 0 to only get IPv6. | +| SAME_IP_ADDRESSES | 0 | The number of identical IP addresses. If the value is 0, random IP addresses will be used | +| STDOUT | terminal | The path to the file. If the value is not equal to `terminal`, then the log is written to a file. Example `STDOUT=/var/log/nginx/access.log` | +| TRUNCATE_FILE | 0 | Truncates the file when opened. `0 `- off, `1` - on | +| STATUS_OK_PERCENT | 80 | _Roughly_ the percentage of `200` status codes. The rest will be randomised and may contain `200` as well. | +| PATH_MIN | 1 | Minimum elements to put in the request path. | +| PATH_MAX | 5 | Maximum elements to put in the request path. | +| GET_PERCENT | 60 | Percentage of requests that will be `GET` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | +| POST_PERCENT | 30 | Percentage of requests that will be `POST` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | +| PUT_PERCENT | 0 | Percentage of requests that will be `PUT` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | +| PATCH_PERCENT | 0 | Percentage of requests that will be `PATCH` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | +| DELETE_PERCENT | 0 | Percentage of requests that will be `DELETE` requests. If the total adds up to less than 100%, the rest will be made up of random HTTP methods. | ## Note diff --git a/main.go b/main.go index 7e31e33..4082d38 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,9 @@ package main import ( "fmt" + "log" "math/rand" + "os" "strings" "time" @@ -14,6 +16,8 @@ type config struct { Rate float32 `env:"RATE" envDefault:"1"` IPv4Percent int `env:"IPV4_PERCENT" envDefault:"100"` SameIpAddresses int `env:"SAME_IP_ADDRESSES" envDefault:"0"` + STDOUT string `env:"STDOUT" envDefault:"terminal"` + TruncateFile int `env:"TRUNCATE_FILE" envDefault:"0"` StatusOkPercent int `env:"STATUS_OK_PERCENT" envDefault:"80"` PathMinLength int `env:"PATH_MIN" envDefault:"1"` PathMaxLength int `env:"PATH_MAX" envDefault:"5"` @@ -49,6 +53,30 @@ func main() { } } + var ( + fileFlags int + file *os.File + err error + ) + + if cfg.STDOUT != "terminal" { + fileFlags = os.O_WRONLY | os.O_CREATE + if cfg.TruncateFile == 1 { + fmt.Println("NGINX LOG GENERATOR [INFO]: open file with truncate") + fileFlags += os.O_TRUNC + } else { + fileFlags += os.O_APPEND + } + + file, err = os.OpenFile(cfg.STDOUT, fileFlags, 0644) + if err != nil { + log.Fatal(err) + } + defer file.Close() + + fmt.Printf("NGINX LOG GENERATOR [INFO]: started writing to %s\n", cfg.STDOUT) + } + for range ticker.C { timeLocal = time.Now() @@ -63,7 +91,12 @@ func main() { bodyBytesSent = realisticBytesSent(statusCode) userAgent = gofakeit.UserAgent() - fmt.Printf("%s - - [%s] \"%s %s %s\" %v %v \"%s\" \"%s\"\n", ip, timeLocal.Format("02/Jan/2006:15:04:05 -0700"), httpMethod, path, httpVersion, statusCode, bodyBytesSent, referrer, userAgent) + logLine := fmt.Sprintf("%s - - [%s] \"%s %s %s\" %v %v \"%s\" \"%s\"\n", ip, timeLocal.Format("02/Jan/2006:15:04:05 -0700"), httpMethod, path, httpVersion, statusCode, bodyBytesSent, referrer, userAgent) + if cfg.STDOUT == "terminal" { + fmt.Print(logLine) + } else { + file.WriteString(logLine) + } } } From 7206c4fb3660d9647ead4c3dc2c334b46501c624 Mon Sep 17 00:00:00 2001 From: steamvis Date: Sat, 23 Jul 2022 12:49:08 +0300 Subject: [PATCH 4/4] Add option to write to file instead of stdout --- Dockerfile | 39 ++++++++------------------------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/Dockerfile b/Dockerfile index b3e1809..57476df 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,39 +1,16 @@ -FROM golang:alpine AS builder +FROM golang:1.18-alpine as build -WORKDIR /workspace - -# Copy in just the go.mod and go.sum files, and download the dependencies. By -# doing this before copying in the other dependencies, the Docker build cache -# can skip these steps so long as neither of these two files change. -COPY go.mod go.sum ./ -RUN go mod download - -# Copy the rest +WORKDIR /go/src/app COPY . . -# Build the Go app with CGO_ENABLED=0 so we use the pure-Go implementations for -# things like DNS resolution (so we don't build a binary that depends on system -# libraries) -RUN CGO_ENABLED=0 go build -o /app - -# Create the 'nobody' user and group files that will be used in the running container to -# run the process an unprivileged user. -RUN mkdir /user && \ - echo 'nobody:x:65534:65534:nobody:/:' > /user/passwd && \ - echo 'nobody:x:65534:' > /user/group +RUN go mod download +RUN CGO_ENABLED=0 go build -o /go/bin/app -# The final stage FROM scratch -# Copy the binary from the builder stage -COPY --from=builder /app /app - -# Copy the /etc/passwd file we created in the builder stage. This creates a new -# non-root user as a security best practice. -COPY --from=builder /user/group /user/passwd /etc/ +COPY --from=build /etc/passwd /etc/passwd +COPY --from=build /etc/group /etc/group -# Run as the new non-root by default -USER nobody:nobody +COPY --from=build /go/bin/app / -# Run the binary -ENTRYPOINT [ "/app" ] \ No newline at end of file +ENTRYPOINT ["/app"] \ No newline at end of file