Skip to content

Add Same IP Addresses #3

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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 8 additions & 31 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -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" ]
ENTRYPOINT ["/app"]
31 changes: 17 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +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. |
| 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

Expand Down
50 changes: 48 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package main

import (
"fmt"
"log"
"math/rand"
"os"
"strings"
"time"

Expand All @@ -12,6 +15,9 @@ 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"`
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"`
Expand Down Expand Up @@ -40,17 +46,57 @@ 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))
}
}

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()

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)
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)
}
}
}

Expand Down