From 0911b8ad6a6aa361889f383c4e26c8cc0b7e4732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Carlos=20Ch=C3=A1vez?= Date: Mon, 30 Oct 2023 15:12:18 +0100 Subject: [PATCH] breaking: removes absolute dir on @owasp_crs directives. (#6) * breaking: removes absolute dir on @owasp_crs directives. The rationale is that the coraza parser will try to resolve an absolute path seeking for the trailing / but the coreruleset files are invoked as @owasp_crs and are supposed to be ubiqutous as long as you include the coreruleset filesystem. * docs: fixes the example. * docs: improves documentation for the wrapper. --- README.md | 10 ++++----- coreruleset.go | 48 ++++++++++++++++++++++++++++++++++++++++++-- coreruleset_test.go | 6 +++++- example/go.mod | 7 +++++-- example/go.sum | 6 ++++++ example/main.go | 2 +- go.mod | 5 ++++- go.sum | 2 ++ io/os.go | 31 ---------------------------- io/os_test.go | 24 ---------------------- io/testdata/test.txt | 1 - 11 files changed, 74 insertions(+), 68 deletions(-) delete mode 100644 io/os.go delete mode 100644 io/os_test.go delete mode 100644 io/testdata/test.txt diff --git a/README.md b/README.md index cb38dc0..a67c468 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,8 @@ You can also combine both CRS and your local files by combining the filesystems: ```go import ( "github.com/corazawaf/coraza-coreruleset" - "github.com/corazawaf/coraza-coreruleset/io" - "github.com/yalue/merged_fs" + "github.com/jcchavezs/mergefs" + "github.com/jcchavezs/mergefs/io" ) // ... @@ -37,7 +37,7 @@ func main() { Include @owasp_crs/REQUEST-911-METHOD-ENFORCEMENT.conf Include my/local/rule.conf `). - WithRootFS(merged_fs.NewMergedFS(coreruleset.FS, io.OSFS)), + WithRootFS(mergefs.Merge(coreruleset.FS, io.OSFS)), ) // ... } @@ -45,6 +45,6 @@ func main() { ## How to update to a newer CRS version -1. Update the `crsVersion` constant in [`version.go`](/version.go) with the wished [CRS](https://github.com/coreruleset/coreruleset) commit SHA. -2. Run `mage downloadCRS`. +1. Update the `crsVersion` constant in [`version.go`](/version.go) with the wished [CRS](https://github.com/coreruleset/coreruleset) commit SHA. +2. Run `mage downloadCRS`. 3. Commit your changes. diff --git a/coreruleset.go b/coreruleset.go index e6acbfc..e221695 100644 --- a/coreruleset.go +++ b/coreruleset.go @@ -4,16 +4,60 @@ import ( "embed" "io/fs" "log" + "strings" ) +// subFS is the interface that contains the methods that are used by +// `fs.subFS` +type subFS interface { + Open(name string) (fs.File, error) + ReadDir(name string) ([]fs.DirEntry, error) + ReadFile(name string) ([]byte, error) + Glob(pattern string) ([]string, error) +} + //go:embed rules/* var wFS embed.FS var FS fs.FS func init() { - var err error - FS, err = fs.Sub(wFS, "rules") + rulesFS, err := fs.Sub(wFS, "rules") if err != nil { log.Fatal(err) } + FS = wrapFS{rulesFS.(subFS)} +} + +// wrapFS is a wrapper around a subFS that removes the absolute path prefix +// from the `name` argument in the ReadFile method. +// The rationale is that the coraza parser when asked to load the files +// invoked by `Include` will prepend the dir path of the parent file. +// For example if you aim to load directives from `my-file.conf which contains`: +// +// `Include @owasp_crs/REQUEST-911-METHOD-ENFORCEMENT.conf` +// +// the way the parser will load the REQUEST-911-METHOD-ENFORCEMENT.conf file +// will depend on how the config was passed on the `WithDirectivesFromFile` method: +// - `my-file.conf`: the dir is "" and hence it will call the RootFS to load +// `@owasp_crs/REQUEST-911-METHOD-ENFORCEMENT.conf` +// - `../my-file.conf`: the dir is `..` and hence it will call the RootFS to load +// `../@owasp_crs/REQUEST-911-METHOD-ENFORCEMENT.conf` which can't be resolved +// because CRS filesyste only holds references to `@owasp_crs“. +// - `/abs-path/my-file.conf`: the dir is `/abs-path` and hence it will call the RootFS +// to load `/abs-path/@owasp_crs/REQUEST-911-METHOD-ENFORCEMENT.conf` which can't +// be resolved because CRS filesystem only holds references to `@owasp_crs`. +// +// The `@owasp_crs` folder is supposed to be ubiqutous as long as you include the coreruleset +// in the same way absolute path is. +type wrapFS struct { + subFS +} + +func (wfs wrapFS) ReadFile(name string) ([]byte, error) { + idx := strings.Index(name, "@") + if idx != -1 { + name = name[idx:] + } + + return wfs.subFS.ReadFile(name) } diff --git a/coreruleset_test.go b/coreruleset_test.go index eb48d97..ba412c9 100644 --- a/coreruleset_test.go +++ b/coreruleset_test.go @@ -7,6 +7,10 @@ import ( ) func TestRules(t *testing.T) { - _, err := FS.Open("@owasp_crs/REQUEST-911-METHOD-ENFORCEMENT.conf") + f, err := FS.Open("@owasp_crs/REQUEST-911-METHOD-ENFORCEMENT.conf") + require.NoError(t, err) + f.Close() + + _, err = FS.(subFS).ReadFile("/usr/src/github.com/myorg/myrepo/@crs-setup.conf.example") require.NoError(t, err) } diff --git a/example/go.mod b/example/go.mod index 946978c..b4662c0 100644 --- a/example/go.mod +++ b/example/go.mod @@ -1,8 +1,11 @@ -module github.com/jcchavezs/coraza-coreruleset/example +module github.com/corazawaf/coraza-coreruleset/example go 1.18 -require github.com/corazawaf/coraza/v3 v3.0.0-20230203191834-6a4986af664c +require ( + github.com/corazawaf/coraza-coreruleset v0.0.0-20230330101229-43b851256042 + github.com/corazawaf/coraza/v3 v3.0.0-20230203191834-6a4986af664c +) require ( github.com/corazawaf/libinjection-go v0.1.2 // indirect diff --git a/example/go.sum b/example/go.sum index 132e064..354338d 100644 --- a/example/go.sum +++ b/example/go.sum @@ -1,13 +1,18 @@ +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-20230203191834-6a4986af664c h1:M9t+XPN3amVVuhFQcH3eOHD0ye7Wi1IquMyinqrfKFI= github.com/corazawaf/coraza/v3 v3.0.0-20230203191834-6a4986af664c/go.mod h1:dXFswKzaDVm4SsHAyvi12A4yLfg2bVx/myCBkyGALGU= 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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6FI= github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo= github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 h1:lL+y4Xv20pVlCGyLzNHRC0I0rIHhIL1lTvHizoS/dU8= github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9/go.mod h1:EHPiTAKtiFmrMldLUNswFwfZ2eJIYBHktdaUTZxYWRw= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -20,3 +25,4 @@ golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/example/main.go b/example/main.go index 173881b..04c4d7b 100644 --- a/example/main.go +++ b/example/main.go @@ -3,9 +3,9 @@ package main import ( "fmt" + "github.com/corazawaf/coraza-coreruleset" coreruleset "github.com/corazawaf/coraza-coreruleset" "github.com/corazawaf/coraza/v3" - "github.com/jcchavezs/coraza-coreruleset" ) func main() { diff --git a/go.mod b/go.mod index 1f25515..0d409a4 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,10 @@ module github.com/corazawaf/coraza-coreruleset go 1.18 -require github.com/stretchr/testify v1.8.2 +require ( + github.com/magefile/mage v1.14.0 + github.com/stretchr/testify v1.8.2 +) require ( github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/go.sum b/go.sum index 6a56e69..d0454cb 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/magefile/mage v1.14.0 h1:6QDX3g6z1YvJ4olPhT1wksUcSa/V0a1B+pJb73fBjyo= +github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= diff --git a/io/os.go b/io/os.go deleted file mode 100644 index 30f713b..0000000 --- a/io/os.go +++ /dev/null @@ -1,31 +0,0 @@ -package io - -import ( - "io/fs" - "os" - "path/filepath" -) - -// Copied from https://github.com/corazawaf/coraza/blob/v3/dev/internal/io/file.go - -// OSFS implements fs.FS using methods on OS to read from the system. -// More context in: https://github.com/golang/go/issues/44279 -type osFS struct{} - -func (osFS) Open(name string) (fs.File, error) { - return os.Open(name) -} - -func (osFS) ReadFile(name string) ([]byte, error) { - return os.ReadFile(name) -} - -func (osFS) ReadDir(name string) ([]fs.DirEntry, error) { - return os.ReadDir(name) -} - -func (osFS) Glob(pattern string) ([]string, error) { - return filepath.Glob(pattern) -} - -var OSFS osFS diff --git a/io/os_test.go b/io/os_test.go deleted file mode 100644 index 32a9303..0000000 --- a/io/os_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package io - -import ( - "errors" - "io/fs" - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestOsFilesystem(t *testing.T) { - t.Run("exists", func(t *testing.T) { - path := "./testdata/test.txt" - _, err := OSFS.Open(path) - assert.NoError(t, err) - }) - - t.Run("does not exist", func(t *testing.T) { - path := "./testdata/doesnotexist.txt" - _, err := OSFS.Open(path) - assert.Error(t, err) - assert.True(t, errors.Is(err, fs.ErrNotExist)) - }) -} diff --git a/io/testdata/test.txt b/io/testdata/test.txt deleted file mode 100644 index f2ba8f8..0000000 --- a/io/testdata/test.txt +++ /dev/null @@ -1 +0,0 @@ -abc \ No newline at end of file