diff --git a/.github/workflows/close-issues.yml b/.github/workflows/close-issues.yml index f8eef9dc6..c4af4c2f6 100644 --- a/.github/workflows/close-issues.yml +++ b/.github/workflows/close-issues.yml @@ -10,7 +10,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@v3 + - uses: actions/stale@v8 with: days-before-issue-stale: 30 days-before-issue-close: 14 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 06d21f0f9..b29985f6b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -10,7 +10,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Initialize CodeQL uses: github/codeql-action/init@v2 diff --git a/.github/workflows/fix-dependabot.yml b/.github/workflows/fix-dependabot.yml index 045aa84ee..3f0b58e1f 100644 --- a/.github/workflows/fix-dependabot.yml +++ b/.github/workflows/fix-dependabot.yml @@ -9,11 +9,11 @@ jobs: runs-on: ubuntu-latest if: ${{ github.actor == 'dependabot[bot]'}} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: - go-version: v1.18.x + go-version: v1.19.x cache: true - name: Format code run: go run mage.go format diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index cf58eed17..0d85ad6f3 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -11,8 +11,8 @@ jobs: name: Fuzz tests runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-go@v1 + - uses: actions/checkout@v4 + - uses: actions/setup-go@v4 with: go-version: '>=1.19.0' - run: go run mage.go fuzz diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 09a77a785..3fa34c03e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -18,9 +18,9 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: v1.19.x cache: true diff --git a/.github/workflows/regression.yml b/.github/workflows/regression.yml index 07bdd84cc..a8c1d8323 100644 --- a/.github/workflows/regression.yml +++ b/.github/workflows/regression.yml @@ -21,9 +21,9 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: ${{ matrix.go-version }} cache: true diff --git a/.github/workflows/tinygo.yml b/.github/workflows/tinygo.yml index b714ce1b2..79f623f1e 100644 --- a/.github/workflows/tinygo.yml +++ b/.github/workflows/tinygo.yml @@ -23,16 +23,16 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Install Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: ${{ matrix.go-version }} cache: true - name: setup tinygo - uses: acifani/setup-tinygo@v1 + uses: acifani/setup-tinygo@v2 with: tinygo-version: 0.27.0 diff --git a/go.mod b/go.mod index 5b4f878f3..8f747bdc2 100644 --- a/go.mod +++ b/go.mod @@ -20,11 +20,11 @@ require ( github.com/corazawaf/libinjection-go v0.1.2 github.com/foxcpp/go-mockdns v1.0.0 github.com/magefile/mage v1.15.0 - github.com/mccutchen/go-httpbin/v2 v2.9.0 + github.com/mccutchen/go-httpbin/v2 v2.12.0 github.com/petar-dambovaliev/aho-corasick v0.0.0-20230725210150-fb29fc3c913e github.com/tidwall/gjson v1.17.0 - golang.org/x/net v0.17.0 - golang.org/x/sync v0.4.0 + golang.org/x/net v0.18.0 + golang.org/x/sync v0.5.0 rsc.io/binaryregexp v0.2.0 ) @@ -33,6 +33,6 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect golang.org/x/mod v0.8.0 // indirect - golang.org/x/sys v0.13.0 // indirect + golang.org/x/sys v0.14.0 // indirect golang.org/x/tools v0.6.0 // indirect ) diff --git a/go.sum b/go.sum index af1b73754..2eaa15578 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6 github.com/foxcpp/go-mockdns v1.0.0/go.mod h1:lgRN6+KxQBawyIghpnl5CezHFGS9VLzvtVlwxvzXTQ4= github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg= github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= -github.com/mccutchen/go-httpbin/v2 v2.9.0 h1:0c8loz/kMEdBmcHJZh0MUgKX84U19AlLk7h6nf2Wkx4= -github.com/mccutchen/go-httpbin/v2 v2.9.0/go.mod h1:+DBHcmg6EOeoizuiOI8iL12VIHXx+9YQNlz+gjB9uxk= +github.com/mccutchen/go-httpbin/v2 v2.12.0 h1:MPrFw/Avug0E83SN/j5SYDuD9By0GDAJ9hNTR4RwjyU= +github.com/mccutchen/go-httpbin/v2 v2.12.0/go.mod h1:f4DUXYlU6yH0V81O4lJIwqpmYdTXXmYwzxMnYEimFPk= github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= @@ -32,12 +32,12 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -47,8 +47,8 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= diff --git a/go.work.sum b/go.work.sum index 050519ddf..21cbdf6ac 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,5 +1,130 @@ -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/pelletier/go-toml v1.9.1/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= +golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/http/interceptor.go b/http/interceptor.go index 6b14aead3..a7b616ab5 100644 --- a/http/interceptor.go +++ b/http/interceptor.go @@ -108,7 +108,23 @@ func (i *rwInterceptor) Header() http.Header { return i.w.Header() } -var _ http.ResponseWriter = (*rwInterceptor)(nil) +func (i *rwInterceptor) ReadFrom(r io.Reader) (n int64, err error) { + return io.Copy(i, r) +} + +func (i *rwInterceptor) Flush() { + if !i.wroteHeader { + i.WriteHeader(http.StatusOK) + } +} + +type responseWriter interface { + http.ResponseWriter + io.ReaderFrom + http.Flusher +} + +var _ responseWriter = (*rwInterceptor)(nil) // wrap wraps the interceptor into a response writer that also preserves // the http interfaces implemented by the original response writer to avoid @@ -168,110 +184,28 @@ func wrap(w http.ResponseWriter, r *http.Request, tx types.Transaction) ( var ( hijacker, isHijacker = i.w.(http.Hijacker) pusher, isPusher = i.w.(http.Pusher) - flusher, isFlusher = i.w.(http.Flusher) - reader, isReader = i.w.(io.ReaderFrom) ) switch { - case !isHijacker && !isPusher && !isFlusher && !isReader: + case !isHijacker && isPusher: return struct { - http.ResponseWriter - }{i}, responseProcessor - case !isHijacker && !isPusher && !isFlusher && isReader: - return struct { - http.ResponseWriter - io.ReaderFrom - }{i, reader}, responseProcessor - case !isHijacker && !isPusher && isFlusher && !isReader: - return struct { - http.ResponseWriter - http.Flusher - }{i, flusher}, responseProcessor - case !isHijacker && !isPusher && isFlusher && isReader: - return struct { - http.ResponseWriter - http.Flusher - io.ReaderFrom - }{i, flusher, reader}, responseProcessor - case !isHijacker && isPusher && !isFlusher && !isReader: - return struct { - http.ResponseWriter + responseWriter http.Pusher }{i, pusher}, responseProcessor - case !isHijacker && isPusher && !isFlusher && isReader: - return struct { - http.ResponseWriter - http.Pusher - io.ReaderFrom - }{i, pusher, reader}, responseProcessor - case !isHijacker && isPusher && isFlusher && !isReader: - return struct { - http.ResponseWriter - http.Pusher - http.Flusher - }{i, pusher, flusher}, responseProcessor - case !isHijacker && isPusher && isFlusher && isReader: + case isHijacker && !isPusher: return struct { - http.ResponseWriter - http.Pusher - http.Flusher - io.ReaderFrom - }{i, pusher, flusher, reader}, responseProcessor - case isHijacker && !isPusher && !isFlusher && !isReader: - return struct { - http.ResponseWriter + responseWriter http.Hijacker }{i, hijacker}, responseProcessor - case isHijacker && !isPusher && !isFlusher && isReader: + case isHijacker && isPusher: return struct { - http.ResponseWriter - http.Hijacker - io.ReaderFrom - }{i, hijacker, reader}, responseProcessor - case isHijacker && !isPusher && isFlusher && !isReader: - return struct { - http.ResponseWriter - http.Hijacker - http.Flusher - }{i, hijacker, flusher}, responseProcessor - case isHijacker && !isPusher && isFlusher && isReader: - return struct { - http.ResponseWriter - http.Hijacker - http.Flusher - io.ReaderFrom - }{i, hijacker, flusher, reader}, responseProcessor - case isHijacker && isPusher && !isFlusher && !isReader: - return struct { - http.ResponseWriter + responseWriter http.Hijacker http.Pusher }{i, hijacker, pusher}, responseProcessor - case isHijacker && isPusher && !isFlusher && isReader: - return struct { - http.ResponseWriter - http.Hijacker - http.Pusher - io.ReaderFrom - }{i, hijacker, pusher, reader}, responseProcessor - case isHijacker && isPusher && isFlusher && !isReader: - return struct { - http.ResponseWriter - http.Hijacker - http.Pusher - http.Flusher - }{i, hijacker, pusher, flusher}, responseProcessor - case isHijacker && isPusher && isFlusher && isReader: - return struct { - http.ResponseWriter - http.Hijacker - http.Pusher - http.Flusher - io.ReaderFrom - }{i, hijacker, pusher, flusher, reader}, responseProcessor default: return struct { - http.ResponseWriter + responseWriter }{i}, responseProcessor } } diff --git a/http/interceptor_test.go b/http/interceptor_test.go index e8424705b..e4da8e700 100644 --- a/http/interceptor_test.go +++ b/http/interceptor_test.go @@ -8,6 +8,10 @@ package http import ( + "bufio" + "bytes" + "io" + "net" "net/http" "net/http/httptest" "testing" @@ -44,3 +48,281 @@ func TestWriteHeader(t *testing.T) { t.Errorf("unexpected status code, want %d, have %d", want, have) } } + +func TestWrite(t *testing.T) { + waf, err := coraza.NewWAF(coraza.NewWAFConfig()) + if err != nil { + t.Fatal(err) + } + + tx := waf.NewTransaction() + req, _ := http.NewRequest("GET", "", nil) + res := httptest.NewRecorder() + + rw, responseProcessor := wrap(res, req, tx) + _, err = rw.Write([]byte("hello")) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + _, err = rw.Write([]byte("world")) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + err = responseProcessor(tx, req) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if want, have := 200, res.Code; want != have { + t.Errorf("unexpected status code, want %d, have %d", want, have) + } +} + +func TestWriteWithWriteHeader(t *testing.T) { + waf, err := coraza.NewWAF(coraza.NewWAFConfig()) + if err != nil { + t.Fatal(err) + } + + tx := waf.NewTransaction() + req, _ := http.NewRequest("GET", "", nil) + res := httptest.NewRecorder() + + rw, responseProcessor := wrap(res, req, tx) + rw.WriteHeader(204) + // although we called WriteHeader, status code should be applied until + // responseProcessor is called. + if unwanted, have := 204, res.Code; unwanted == have { + t.Errorf("unexpected status code %d", have) + } + + _, err = rw.Write([]byte("hello")) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + _, err = rw.Write([]byte("world")) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + err = responseProcessor(tx, req) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if want, have := 204, res.Code; want != have { + t.Errorf("unexpected status code, want %d, have %d", want, have) + } +} + +func TestFlush(t *testing.T) { + waf, err := coraza.NewWAF(coraza.NewWAFConfig()) + if err != nil { + t.Fatal(err) + } + + t.Run("WriteHeader before Flush", func(t *testing.T) { + tx := waf.NewTransaction() + req, _ := http.NewRequest("GET", "", nil) + res := httptest.NewRecorder() + rw, responseProcessor := wrap(res, req, tx) + rw.WriteHeader(204) + rw.(http.Flusher).Flush() + // although we called WriteHeader, status code should be applied until + // responseProcessor is called. + if unwanted, have := 204, res.Code; unwanted == have { + t.Errorf("unexpected status code %d", have) + } + + err = responseProcessor(tx, req) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if want, have := 204, res.Code; want != have { + t.Errorf("unexpected status code, want %d, have %d", want, have) + } + }) + + t.Run("Flush before WriteHeader", func(t *testing.T) { + tx := waf.NewTransaction() + req, _ := http.NewRequest("GET", "", nil) + res := httptest.NewRecorder() + rw, responseProcessor := wrap(res, req, tx) + rw.(http.Flusher).Flush() + rw.WriteHeader(204) + + if want, have := 200, res.Code; want != have { + t.Errorf("unexpected status code, want %d, have %d", want, have) + } + + err = responseProcessor(tx, req) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if want, have := 200, res.Code; want != have { + t.Errorf("unexpected status code, want %d, have %d", want, have) + } + }) +} + +type testReaderFrom struct { + io.Writer +} + +func (x *testReaderFrom) ReadFrom(r io.Reader) (n int64, err error) { + return io.Copy(x, r) +} + +func TestReadFrom(t *testing.T) { + waf, err := coraza.NewWAF(coraza.NewWAFConfig()) + if err != nil { + t.Fatal(err) + } + + tx := waf.NewTransaction() + req, _ := http.NewRequest("GET", "", nil) + res := httptest.NewRecorder() + + type responseWriter interface { + http.ResponseWriter + http.Flusher + } + + resWithReaderFrom := struct { + responseWriter + io.ReaderFrom + }{ + res, + &testReaderFrom{res}, + } + + rw, responseProcessor := wrap(resWithReaderFrom, req, tx) + rw.WriteHeader(204) + // although we called WriteHeader, status code should be applied until + // responseProcessor is called. + if unwanted, have := 204, res.Code; unwanted == have { + t.Errorf("unexpected status code %d", have) + } + + _, err = rw.(io.ReaderFrom).ReadFrom(bytes.NewBuffer([]byte("hello world"))) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + err = responseProcessor(tx, req) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + + if want, have := 204, res.Code; want != have { + t.Errorf("unexpected status code, want %d, have %d", want, have) + } +} + +type testPusher struct{} + +func (x *testPusher) Push(string, *http.PushOptions) error { + return nil +} + +type testHijacker struct{} + +func (x *testHijacker) Hijack() (net.Conn, *bufio.ReadWriter, error) { + return nil, nil, nil +} + +func TestInterface(t *testing.T) { + waf, err := coraza.NewWAF(coraza.NewWAFConfig()) + if err != nil { + t.Fatal(err) + } + + tx := waf.NewTransaction() + req, _ := http.NewRequest("GET", "", nil) + res := httptest.NewRecorder() + + t.Run("default", func(t *testing.T) { + rw, _ := wrap(struct { + http.ResponseWriter + }{ + res, + }, req, tx) + + _, ok := rw.(http.Pusher) + if ok { + t.Errorf("expected the wrapped ResponseWriter to not implement http.Pusher") + } + + _, ok = rw.(http.Hijacker) + if ok { + t.Errorf("expected the wrapped ResponseWriter to not implement http.Hijacker") + } + }) + + t.Run("http.Pusher", func(t *testing.T) { + rw, _ := wrap(struct { + http.ResponseWriter + http.Pusher + }{ + res, + &testPusher{}, + }, req, tx) + + _, ok := rw.(http.Pusher) + if !ok { + t.Errorf("expected the wrapped ResponseWriter to implement http.Pusher") + } + + _, ok = rw.(http.Hijacker) + if ok { + t.Errorf("expected the wrapped ResponseWriter to not implement http.Hijacker") + } + }) + + t.Run("http.Hijacker", func(t *testing.T) { + rw, _ := wrap(struct { + http.ResponseWriter + http.Hijacker + }{ + res, + &testHijacker{}, + }, req, tx) + + _, ok := rw.(http.Hijacker) + if !ok { + t.Errorf("expected the wrapped ResponseWriter to implement http.Hijacker") + } + + _, ok = rw.(http.Pusher) + if ok { + t.Errorf("expected the wrapped ResponseWriter to not implement http.Pusher") + } + }) + + t.Run("http.Hijacker and http.Pusher", func(t *testing.T) { + rw, _ := wrap(struct { + http.ResponseWriter + http.Hijacker + http.Pusher + }{ + res, + &testHijacker{}, + &testPusher{}, + }, req, tx) + + _, ok := rw.(http.Hijacker) + if !ok { + t.Errorf("expected the wrapped ResponseWriter to implement http.Hijacker") + } + + _, ok = rw.(http.Pusher) + if !ok { + t.Errorf("expected the wrapped ResponseWriter to implement http.Pusher") + } + }) +} diff --git a/internal/auditlog/concurrent_writer.go b/internal/auditlog/concurrent_writer.go index fab2382cc..ab6d4bcc0 100644 --- a/internal/auditlog/concurrent_writer.go +++ b/internal/auditlog/concurrent_writer.go @@ -55,6 +55,15 @@ func (cl concurrentWriter) Write(al plugintypes.AuditLog) error { return nil } + formattedAL, err := cl.formatter.Format(al) + if err != nil { + return err + } + + if len(formattedAL) == 0 { + return nil + } + // 192.168.3.130 192.168.3.1 - - [22/Aug/2009:13:24:20 +0100] "GET / HTTP/1.1" 200 56 "-" "-" SojdH8AAQEAAAugAQAAAAAA "-" /20090822/20090822-1324/20090822-132420-SojdH8AAQEAAAugAQAAAAAA 0 1248 t := time.Unix(0, al.Transaction().UnixTimestamp()) @@ -67,11 +76,6 @@ func (cl concurrentWriter) Write(al plugintypes.AuditLog) error { return err } - formattedAL, err := cl.formatter.Format(al) - if err != nil { - return err - } - filepath := path.Join(logdir, filename) if err = os.WriteFile(filepath, formattedAL, cl.logFileMode); err != nil { return err diff --git a/internal/auditlog/concurrent_writer_test.go b/internal/auditlog/concurrent_writer_test.go index 1cbde6613..f3511bec5 100644 --- a/internal/auditlog/concurrent_writer_test.go +++ b/internal/auditlog/concurrent_writer_test.go @@ -8,6 +8,7 @@ package auditlog import ( "encoding/json" + "errors" "fmt" "io/fs" "os" @@ -46,7 +47,51 @@ func TestConcurrentWriterFailsOnInit(t *testing.T) { } } -func TestConcurrentWriterWrites(t *testing.T) { +type mockFormatter struct { + plugintypes.AuditLogFormatter + formatted []byte + err error +} + +func (ef mockFormatter) Format(plugintypes.AuditLog) ([]byte, error) { + return ef.formatted, ef.err +} + +func TestConcurrentWriter(t *testing.T) { + t.Run("empty formatted", func(t *testing.T) { + config := plugintypes.AuditLogConfig{ + Target: os.DevNull, + Formatter: mockFormatter{}, + } + + writer := &concurrentWriter{} + if err := writer.Init(config); err != nil { + t.Errorf("unexpected error: %v", err) + } + + if err := writer.Write(nil); err != nil { + t.Errorf("unexpected error: %v", err) + } + }) + + t.Run("formatting error", func(t *testing.T) { + config := plugintypes.AuditLogConfig{ + Target: os.DevNull, + Formatter: mockFormatter{err: errors.New("formatting error")}, + } + + writer := &concurrentWriter{} + if err := writer.Init(config); err != nil { + t.Errorf("unexpected error: %v", err) + } + + if err := writer.Write(nil); err == nil { + t.Errorf("expected error: %v", err) + } + }) +} + +func TestConcurrentWriterSuccess(t *testing.T) { dir := t.TempDir() file, err := os.Create(filepath.Join(dir, "audit.log")) if err != nil { @@ -59,6 +104,12 @@ func TestConcurrentWriterWrites(t *testing.T) { DirMode: fs.FileMode(0777), Formatter: &jsonFormatter{}, } + + writer := &concurrentWriter{} + if err := writer.Init(config); err != nil { + t.Error("failed to init concurrent logger", err) + } + ts := time.Now() expectedLog := &Log{ Transaction_: Transaction{ @@ -74,10 +125,6 @@ func TestConcurrentWriterWrites(t *testing.T) { }, }, } - writer := &concurrentWriter{} - if err := writer.Init(config); err != nil { - t.Error("failed to init concurrent logger", err) - } if err := writer.Write(expectedLog); err != nil { t.Error("failed to write to logger: ", err) } diff --git a/internal/auditlog/formats.go b/internal/auditlog/formats.go index 82ad71d05..dab2c91c4 100644 --- a/internal/auditlog/formats.go +++ b/internal/auditlog/formats.go @@ -31,6 +31,10 @@ import ( type nativeFormatter struct{} func (nativeFormatter) Format(al plugintypes.AuditLog) ([]byte, error) { + if len(al.Parts()) == 0 { + return nil, nil + } + boundaryPrefix := fmt.Sprintf("--%s-", utils.RandomString(10)) var res strings.Builder @@ -56,31 +60,36 @@ func (nativeFormatter) Format(al plugintypes.AuditLog) ([]byte, error) { // Content-Length: 6 _, _ = fmt.Fprintf( &res, - "%s %s %s\n", + "\n%s %s %s", al.Transaction().Request().Method(), al.Transaction().Request().URI(), al.Transaction().Request().Protocol(), ) for k, vv := range al.Transaction().Request().Headers() { for _, v := range vv { + res.WriteByte('\n') res.WriteString(k) res.WriteString(": ") res.WriteString(v) - res.WriteByte('\n') } } case types.AuditLogPartRequestBody: - // b=test - res.WriteString(al.Transaction().Request().Body()) + if body := al.Transaction().Request().Body(); body != "" { + res.WriteByte('\n') + res.WriteString(body) + } case types.AuditLogPartIntermediaryResponseBody: - res.WriteString(al.Transaction().Response().Body()) + if body := al.Transaction().Response().Body(); body != "" { + res.WriteByte('\n') + res.WriteString(al.Transaction().Response().Body()) + } case types.AuditLogPartResponseHeaders: for k, vv := range al.Transaction().Response().Headers() { for _, v := range vv { + res.WriteByte('\n') res.WriteString(k) res.WriteString(": ") res.WriteString(v) - res.WriteByte('\n') } } case types.AuditLogPartAuditLogTrailer: @@ -91,11 +100,11 @@ func (nativeFormatter) Format(al plugintypes.AuditLog) ([]byte, error) { // Producer: ModSecurity for Apache/2.9.1 (http://www.modsecurity.org/). // Server: Apache // Engine-Mode: "ENABLED" - _, _ = fmt.Fprintf(&res, "Stopwatch: %s\nResponse-Body-Transformed: %s\nProducer: %s\nServer: %s", "", "", "", "") + _, _ = fmt.Fprintf(&res, "\nStopwatch: %s\nResponse-Body-Transformed: %s\nProducer: %s\nServer: %s", "", "", "", "") case types.AuditLogPartRulesMatched: for _, r := range al.Messages() { - res.WriteString(r.Data().Raw()) res.WriteByte('\n') + res.WriteString(r.Data().Raw()) } } res.WriteByte('\n') diff --git a/internal/auditlog/formats_test.go b/internal/auditlog/formats_test.go index 68712a2d1..91381aad4 100644 --- a/internal/auditlog/formats_test.go +++ b/internal/auditlog/formats_test.go @@ -4,7 +4,9 @@ package auditlog import ( + "bufio" "bytes" + "fmt" "strings" "testing" @@ -12,20 +14,77 @@ import ( "github.com/corazawaf/coraza/v3/types" ) +func checkLine(t *testing.T, lines []string, index int, expected string) { + t.Helper() + if lines[index] != expected { + auditLog := &strings.Builder{} + auditLog.WriteByte('\n') + for i, line := range lines { + auditLog.WriteString(fmt.Sprintf("Line %d: ", i)) + auditLog.WriteString(line) + auditLog.WriteByte('\n') + } + t.Log(auditLog.String()) + t.Fatalf("unexpected line %d, \ngot: %q\nwant: %q\n", index, lines[index], expected) + } +} + +func mutateSeparator(separator string, part byte) string { + return separator[:len(separator)-3] + string(part) + separator[len(separator)-2:] +} + func TestNativeFormatter(t *testing.T) { - al := createAuditLog() f := &nativeFormatter{} - data, err := f.Format(al) - if err != nil { - t.Error(err) - } - if !strings.Contains(f.MIME(), "x-coraza-auditlog-native") { - t.Errorf("failed to match MIME, expected json and got %s", f.MIME()) - } - // Log contains random strings, do a simple sanity check - if !bytes.Contains(data, []byte("[02/Jan/2006:15:04:20 -0700] 123 0 0")) { - t.Errorf("failed to match log, \ngot: %s\n", string(data)) - } + + t.Run("empty parts", func(t *testing.T) { + al := &Log{} + l, err := f.Format(al) + if l != nil { + t.Error("expected nil log") + } + if err != nil { + t.Error("unexpected error") + } + }) + + t.Run("success", func(t *testing.T) { + al := createAuditLog() + data, err := f.Format(al) + if err != nil { + t.Error(err) + } + if !strings.Contains(f.MIME(), "x-coraza-auditlog-native") { + t.Errorf("failed to match MIME, expected json and got %s", f.MIME()) + } + // Log contains random strings, do a simple sanity check + if !bytes.Contains(data, []byte("[02/Jan/2006:15:04:20 -0700] 123 0 0")) { + t.Errorf("failed to match log, \ngot: %s\n", string(data)) + } + + scanner := bufio.NewScanner(bytes.NewReader(data)) + + var lines []string + for scanner.Scan() { + lines = append(lines, scanner.Text()) + } + separator := lines[0] + + checkLine(t, lines, 2, "GET /test.php HTTP/1.1") + checkLine(t, lines, 3, "some: request header") + checkLine(t, lines, 4, mutateSeparator(separator, 'C')) + checkLine(t, lines, 6, "some request body") + checkLine(t, lines, 7, mutateSeparator(separator, 'E')) + checkLine(t, lines, 9, "some response body") + checkLine(t, lines, 10, mutateSeparator(separator, 'F')) + checkLine(t, lines, 12, "some: response header") + checkLine(t, lines, 13, mutateSeparator(separator, 'H')) + checkLine(t, lines, 15, "Stopwatch: ") + checkLine(t, lines, 16, "Response-Body-Transformed: ") + checkLine(t, lines, 17, "Producer: ") + checkLine(t, lines, 18, "Server: ") + checkLine(t, lines, 19, mutateSeparator(separator, 'K')) + checkLine(t, lines, 21, `SecAction "id:100"`) + }) } func createAuditLog() *Log { @@ -47,17 +106,20 @@ func createAuditLog() *Log { Method_: "GET", Headers_: map[string][]string{ "some": { - "somedata", + "request header", }, }, + Body_: "some request body", + Protocol_: "HTTP/1.1", }, Response_: &TransactionResponse{ Status_: 200, Headers_: map[string][]string{ "some": { - "somedata", + "response header", }, }, + Body_: "some response body", }, Producer_: &TransactionProducer{ Connector_: "some connector", diff --git a/internal/auditlog/serial_writer.go b/internal/auditlog/serial_writer.go index d752d541a..9626db0ae 100644 --- a/internal/auditlog/serial_writer.go +++ b/internal/auditlog/serial_writer.go @@ -54,6 +54,11 @@ func (sl *serialWriter) Write(al plugintypes.AuditLog) error { if err != nil { return err } + + if len(bts) == 0 { + return nil + } + sl.logger.Println(string(bts)) return nil } diff --git a/internal/corazawaf/waf.go b/internal/corazawaf/waf.go index 0ec203140..0f8c8430f 100644 --- a/internal/corazawaf/waf.go +++ b/internal/corazawaf/waf.go @@ -283,8 +283,14 @@ func NewWAF() *WAF { auditLogWriter: logWriter, auditLogWriterInitialized: false, AuditLogWriterConfig: auditlog.NewConfig(), - Logger: logger, - ArgumentLimit: 1000, + AuditLogParts: types.AuditLogParts{ + types.AuditLogPartRequestHeaders, + types.AuditLogPartRequestBody, + types.AuditLogPartResponseHeaders, + types.AuditLogPartAuditLogTrailer, + }, + Logger: logger, + ArgumentLimit: 1000, } if environment.HasAccessToFS { diff --git a/renovate.json b/renovate.json new file mode 100644 index 000000000..5db72dd6a --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ] +} diff --git a/testing/coreruleset/go.mod b/testing/coreruleset/go.mod index be4b7e831..4ef4f8a16 100644 --- a/testing/coreruleset/go.mod +++ b/testing/coreruleset/go.mod @@ -3,11 +3,11 @@ module github.com/corazawaf/coraza/v3/testing/coreruleset go 1.18 require ( - github.com/bmatcuk/doublestar/v4 v4.3.0 + github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/corazawaf/coraza-coreruleset v0.0.0-20230330101229-43b851256042 - github.com/corazawaf/coraza/v3 v3.0.0-20221004054810-060cedcb166d + github.com/corazawaf/coraza/v3 v3.0.4 github.com/coreruleset/go-ftw v0.4.9 - github.com/rs/zerolog v1.28.0 + github.com/rs/zerolog v1.31.0 ) require ( @@ -26,7 +26,7 @@ require ( github.com/kyokomi/emoji v2.2.4+incompatible // indirect github.com/magefile/mage v1.15.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect @@ -35,10 +35,11 @@ require ( github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/yargevad/filepathx v1.0.0 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/tools v0.6.0 // indirect + golang.org/x/crypto v0.15.0 // indirect + golang.org/x/net v0.18.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.14.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + rsc.io/binaryregexp v0.2.0 // indirect ) diff --git a/testing/coreruleset/go.sum b/testing/coreruleset/go.sum index ff20fd632..c666c7eef 100644 --- a/testing/coreruleset/go.sum +++ b/testing/coreruleset/go.sum @@ -31,8 +31,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bmatcuk/doublestar/v4 v4.3.0 h1:Ct0GphHCZaXvUh2Gqtk37Mzj1qWvXcW9XnXQs1GL9S0= -github.com/bmatcuk/doublestar/v4 v4.3.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= +github.com/bmatcuk/doublestar/v4 v4.6.1 h1:FH9SifrbvJhnlQpztAx++wlkk70QBf0iBWDwNy7PA4I= +github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -40,13 +40,13 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/corazawaf/coraza-coreruleset v0.0.0-20230330101229-43b851256042 h1:WMAVBbS+u1zopf0gT1UBTtmmxVRCj9gY1dmnT14PsZM= github.com/corazawaf/coraza-coreruleset v0.0.0-20230330101229-43b851256042/go.mod h1:h7fBXlh00atH/uVC9Lpjawg/RlJCsHjvyVk+bP3ylq8= -github.com/corazawaf/coraza/v3 v3.0.0-20221004054810-060cedcb166d h1:e7nLsrnie6309FYWPZg2kY2yQWhHslmfkzZTPVnpeqg= -github.com/corazawaf/coraza/v3 v3.0.0-20221004054810-060cedcb166d/go.mod h1:+ypLPFkX5j1GwKi+rqRZ57W3lSHReBdeVLh0o8qirI4= +github.com/corazawaf/coraza/v3 v3.0.4 h1:Llemgoh0hp2NggCwcWN8lNiV4Pfe+AWzf1oEcasT234= +github.com/corazawaf/coraza/v3 v3.0.4/go.mod h1:3fTYjY5BZv3nezLpH6NAap0gr3jZfbQWUAu2GF17ET4= github.com/corazawaf/libinjection-go v0.1.2 h1:oeiV9pc5rvJ+2oqOqXEAMJousPpGiup6f7Y3nZj5GoM= github.com/corazawaf/libinjection-go v0.1.2/go.mod h1:OP4TM7xdJ2skyXqNX1AN1wN5nNZEmJNuWbNPOItn7aw= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreruleset/go-ftw v0.4.9 h1:4s4GPnn07d1S58QhoZlWy6UTdpjCTzhnhsfmh1cJ7E8= github.com/coreruleset/go-ftw v0.4.9/go.mod h1:VLRHyrid8L2gB5AsnHpQnHfizBkZpKZuy3OUq0s8rCc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -201,7 +201,6 @@ github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVc github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -210,8 +209,9 @@ github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcME github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= @@ -271,9 +271,9 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY= -github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= +github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= @@ -314,8 +314,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -343,8 +343,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -357,6 +357,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -388,11 +390,12 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -413,7 +416,6 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -468,4 +470,6 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/waf.go b/waf.go index 348cafad3..30382c174 100644 --- a/waf.go +++ b/waf.go @@ -57,19 +57,7 @@ func NewWAF(config WAFConfig) (WAF, error) { } } - if a := c.auditLog; a != nil { - if a.relevantOnly { - waf.AuditEngine = types.AuditEngineRelevantOnly - } else { - waf.AuditEngine = types.AuditEngineOn - } - - waf.AuditLogParts = a.parts - - if a.writer != nil { - waf.SetAuditLogWriter(a.writer) - } - } + populateAuditLog(waf, c) if err := waf.InitAuditLogWriter(); err != nil { return nil, fmt.Errorf("invalid WAF config from audit log: %w", err) @@ -110,6 +98,26 @@ func NewWAF(config WAFConfig) (WAF, error) { return wafWrapper{waf: waf}, nil } +func populateAuditLog(waf *corazawaf.WAF, c *wafConfig) { + if c.auditLog == nil { + return + } + + if c.auditLog.relevantOnly { + waf.AuditEngine = types.AuditEngineRelevantOnly + } else { + waf.AuditEngine = types.AuditEngineOn + } + + if len(c.auditLog.parts) > 0 { + waf.AuditLogParts = c.auditLog.parts + } + + if c.auditLog.writer != nil { + waf.SetAuditLogWriter(c.auditLog.writer) + } +} + type wafWrapper struct { waf *corazawaf.WAF } diff --git a/waf_test.go b/waf_test.go index 08d52dfb6..d4ee3e9e6 100644 --- a/waf_test.go +++ b/waf_test.go @@ -5,7 +5,12 @@ package coraza import ( "errors" + "reflect" "testing" + + "github.com/corazawaf/coraza/v3/experimental/plugins/plugintypes" + "github.com/corazawaf/coraza/v3/internal/corazawaf" + "github.com/corazawaf/coraza/v3/types" ) func TestRequestBodyLimit(t *testing.T) { @@ -103,3 +108,73 @@ func TestResponseBodyLimit(t *testing.T) { }) } } + +type testAuditLogWriter struct { + plugintypes.AuditLogWriter +} + +func (*testAuditLogWriter) Init(plugintypes.AuditLogConfig) error { + return nil +} + +func TestPopulateAuditLog(t *testing.T) { + writer := &testAuditLogWriter{} + + testCases := map[string]struct { + config *wafConfig + check func(*testing.T, *corazawaf.WAF) + }{ + "empty config": { + config: &wafConfig{}, + check: func(*testing.T, *corazawaf.WAF) {}, + }, + "with relevant only": { + config: &wafConfig{ + auditLog: &auditLogConfig{ + relevantOnly: true, + }, + }, + check: func(t *testing.T, waf *corazawaf.WAF) { + if waf.AuditEngine != types.AuditEngineRelevantOnly { + t.Fatal("expected AuditLogRelevantOnly to be true") + } + }, + }, + "with parts": { + config: &wafConfig{ + auditLog: &auditLogConfig{ + parts: []types.AuditLogPart{ + types.AuditLogPartRequestHeaders, + types.AuditLogPartResponseBody, + }, + }, + }, + check: func(t *testing.T, waf *corazawaf.WAF) { + if want, have := []types.AuditLogPart{ + types.AuditLogPartRequestHeaders, + types.AuditLogPartResponseBody, + }, waf.AuditLogParts; len(want) != len(have) { + t.Fatalf("unexpected AuditLogParts: want %v, have %v", want, have) + } + }, + }, + "with audit log writer": { + config: &wafConfig{ + auditLog: &auditLogConfig{writer: writer}, + }, + check: func(t *testing.T, waf *corazawaf.WAF) { + if reflect.DeepEqual(waf.AuditLogWriter(), &writer) { + t.Fatal("expected AuditLogWriter to be set") + } + }, + }, + } + + for name, tCase := range testCases { + t.Run(name, func(t *testing.T) { + waf := &corazawaf.WAF{} + populateAuditLog(waf, tCase.config) + tCase.check(t, waf) + }) + } +}