From 4ca2780dbf19d137746041886525fdebe594e50a Mon Sep 17 00:00:00 2001 From: runner361 Date: Sun, 29 May 2022 07:54:48 +0800 Subject: [PATCH 1/4] Fix issue 4961 Fix issue 4961, `leafInfo.match()` use `path.join()` to deal with `wildcardValues`, which may lead to cross directory risk --- CHANGELOG.md | 2 +- server/web/tree.go | 2 ++ server/web/tree_test.go | 11 ++++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0075ddcf..3745e2b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ # developing - +- [Fix issue 4961, `leafInfo.match()` use `path.join()` to deal with `wildcardValues`, which may lead to cross directory risk ](https://github.com/beego/beego/pull/4964) # v2.0.3 - [upgrade redisgo to v1.8.8](https://github.com/beego/beego/pull/4872) - [fix prometheus CVE-2022-21698](https://github.com/beego/beego/pull/4878) diff --git a/server/web/tree.go b/server/web/tree.go index 3e0b86c5..adcb8853 100644 --- a/server/web/tree.go +++ b/server/web/tree.go @@ -282,6 +282,8 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string, // Match router to runObject & params func (t *Tree) Match(pattern string, ctx *context.Context) (runObject interface{}) { + // fix issue 4961, deal with "./ ../ //" + pattern = path.Clean(pattern) if pattern == "" || pattern[0] != '/' { return nil } diff --git a/server/web/tree_test.go b/server/web/tree_test.go index f43c4a87..af0c888e 100644 --- a/server/web/tree_test.go +++ b/server/web/tree_test.go @@ -68,7 +68,8 @@ func init() { matchTestInfo("/", "/", nil), matchTestInfo("/customer/login", "/customer/login", nil), matchTestInfo("/customer/login", "/customer/login.json", map[string]string{":ext": "json"}), - matchTestInfo("/*", "/http://customer/123/", map[string]string{":splat": "http://customer/123/"}), + // This case need to be modified when fix issue 4961, "//" will be replaced with "/" and last "/" will be deleted before route. + matchTestInfo("/*", "/http://customer/123/", map[string]string{":splat": "http:/customer/123"}), matchTestInfo("/*", "/customer/2009/12/11", map[string]string{":splat": "customer/2009/12/11"}), matchTestInfo("/aa/*/bb", "/aa/2009/bb", map[string]string{":splat": "2009"}), matchTestInfo("/cc/*/dd", "/cc/2009/11/dd", map[string]string{":splat": "2009/11"}), @@ -125,6 +126,14 @@ func init() { // test for fix of issue 4946 notMatchTestInfo("/suffix/:name", "/suffix.html/suffix.html"), matchTestInfo("/suffix/:id/name", "/suffix/1234/name.html", map[string]string{":id": "1234", ":ext": "html"}), + // test for fix of issue 4961,path.join() lead to cross directory risk + matchTestInfo("/book1/:name/fixPath1/*.*", "/book1/name1/fixPath1/mybook/../mybook2.txt", map[string]string{":name": "name1", ":path": "mybook2"}), + notMatchTestInfo("/book1/:name/fixPath1/*.*", "/book1/name1/fixPath1/mybook/../../mybook2.txt"), + notMatchTestInfo("/book1/:name/fixPath1/*.*", "/book1/../fixPath1/mybook/../././////evil.txt"), + notMatchTestInfo("/book1/:name/fixPath1/*.*", "/book1/./fixPath1/mybook/../././////evil.txt"), + notMatchTestInfo("/book2/:type:string/fixPath1/:name", "/book2/type1/fixPath1/name1/../../././////evilType/evilName"), + notMatchTestInfo("/book2/:type:string/fixPath1/:name", "/book2/type1/fixPath1/name1/../../././////evilType/evilName"), + notMatchTestInfo("/book2/:type:string/fixPath1/:name", "/book2/type1/fixPath1/name1/../../././////evilType/evilName"), } } From f2c28be167a83517869b84509a14c49bb9157897 Mon Sep 17 00:00:00 2001 From: Dokiy Date: Thu, 19 May 2022 11:30:09 +0800 Subject: [PATCH 2/4] feat: add orm opentelemetry filter --- CHANGELOG.md | 1 + client/orm/filter/opentelemetry/filter.go | 90 +++++++++++++++++++ .../orm/filter/opentelemetry/filter_test.go | 61 +++++++++++++ go.mod | 2 + go.sum | 5 ++ 5 files changed, 159 insertions(+) create mode 100644 client/orm/filter/opentelemetry/filter.go create mode 100644 client/orm/filter/opentelemetry/filter_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 95519189..a0cd9782 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - [upgrade to Go 1.18](https://github.com/beego/beego/pull/4896) - [make `PatternLogFormatter` handling the arguments](https://github.com/beego/beego/pull/4914/files) - [Add httplib OpenTelemetry Filter](https://github.com/beego/beego/pull/4888, https://github.com/beego/beego/pull/4915) +- [Add orm OpenTelemetry Filter](https://github.com/beego/beego/issues/4944) - [Support NewBeegoRequestWithCtx in httplib](https://github.com/beego/beego/pull/4895) - [Support lifecycle callback](https://github.com/beego/beego/pull/4918) - [logs: multiFileLogWriter uses incorrect formatter](https://github.com/beego/beego/pull/4943) diff --git a/client/orm/filter/opentelemetry/filter.go b/client/orm/filter/opentelemetry/filter.go new file mode 100644 index 00000000..d33109ca --- /dev/null +++ b/client/orm/filter/opentelemetry/filter.go @@ -0,0 +1,90 @@ +// Copyright 2020 beego +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package opentelemetry + +import ( + "context" + "strings" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + otelTrace "go.opentelemetry.io/otel/trace" + + "github.com/beego/beego/v2/client/orm" +) + +type ( + CustomSpanFunc func(ctx context.Context, span otelTrace.Span, inv *orm.Invocation) + FilterChainOption func(fcv *FilterChainBuilder) +) + +// FilterChainBuilder provides an opentelemtry Filter +type FilterChainBuilder struct { + // customSpanFunc users are able to custom their span + customSpanFunc CustomSpanFunc +} + +func NewFilterChainBuilder(options ...FilterChainOption) *FilterChainBuilder { + fcb := &FilterChainBuilder{} + for _, o := range options { + o(fcb) + } + return fcb +} + +// WithCustomSpanFunc add function to custom span +func WithCustomSpanFunc(customSpanFunc CustomSpanFunc) FilterChainOption { + return func(fcv *FilterChainBuilder) { + fcv.customSpanFunc = customSpanFunc + } +} + +// FilterChain traces invocation with opentelemetry +// Unless invocation.Method is Begin*, Commit or Rollback +func (builder *FilterChainBuilder) FilterChain(next orm.Filter) orm.Filter { + return func(ctx context.Context, inv *orm.Invocation) []interface{} { + if strings.HasPrefix(inv.Method, "Begin") || inv.Method == "Commit" || inv.Method == "Rollback" { + return next(ctx, inv) + } + spanCtx, span := otel.Tracer("beego_orm").Start(ctx, invOperationName(ctx, inv)) + defer span.End() + + res := next(spanCtx, inv) + builder.buildSpan(spanCtx, span, inv) + return res + } +} + +// buildSpan add default span attributes and custom attributes with customSpanFunc +func (builder *FilterChainBuilder) buildSpan(ctx context.Context, span otelTrace.Span, inv *orm.Invocation) { + span.SetAttributes(attribute.String("orm.method", inv.Method)) + span.SetAttributes(attribute.String("orm.table", inv.GetTableName())) + span.SetAttributes(attribute.Bool("orm.insideTx", inv.InsideTx)) + v, _ := ctx.Value(orm.TxNameKey).(string) + span.SetAttributes(attribute.String("orm.txName", v)) + span.SetAttributes(attribute.String("span.kind", "client")) + span.SetAttributes(attribute.String("component", "beego")) + + if builder.customSpanFunc != nil { + builder.customSpanFunc(ctx,span, inv) + } +} + +func invOperationName(ctx context.Context, inv *orm.Invocation) string { + if n, ok := ctx.Value(orm.TxNameKey).(string); ok { + return inv.Method + "#tx(" + n + ")" + } + return inv.Method + "#" + inv.GetTableName() +} diff --git a/client/orm/filter/opentelemetry/filter_test.go b/client/orm/filter/opentelemetry/filter_test.go new file mode 100644 index 00000000..589cb320 --- /dev/null +++ b/client/orm/filter/opentelemetry/filter_test.go @@ -0,0 +1,61 @@ +// Copyright 2020 beego +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package opentelemetry + +import ( + "bytes" + "context" + "testing" + + "github.com/stretchr/testify/assert" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" + "go.opentelemetry.io/otel/sdk/trace" + otelTrace "go.opentelemetry.io/otel/trace" + + "github.com/beego/beego/v2/client/orm" +) + +func TestFilterChainBuilderFilterChain(t *testing.T) { + // Init Trace + buf := bytes.NewBuffer([]byte{}) + exp, err := stdouttrace.New(stdouttrace.WithWriter(buf)) + if err != nil { + t.Error(err) + } + tp := trace.NewTracerProvider(trace.WithBatcher(exp)) + otel.SetTracerProvider(tp) + + // Build FilterChain + csf := func(ctx context.Context, span otelTrace.Span, inv *orm.Invocation) { + span.SetAttributes(attribute.String("hello", "work")) + } + builder := NewFilterChainBuilder(WithCustomSpanFunc(csf)) + + inv := &orm.Invocation{Method: "Hello"} + next := func(ctx context.Context, inv *orm.Invocation) []interface{} { return nil } + + builder.FilterChain(next)(context.Background(), inv) + + // Close tp + err = tp.Shutdown(context.Background()) + if err != nil { + t.Error(err) + } + + // Assert opentelemetry span name + assert.Equal(t, "Hello#", string(buf.Bytes()[9:15])) +} diff --git a/go.mod b/go.mod index 448dc825..24f443b6 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,8 @@ require ( github.com/stretchr/testify v1.7.1 go.etcd.io/etcd/client/v3 v3.5.4 go.opentelemetry.io/otel v1.7.0 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.7.0 + go.opentelemetry.io/otel/sdk v1.7.0 go.opentelemetry.io/otel/trace v1.7.0 golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a google.golang.org/grpc v1.38.0 diff --git a/go.sum b/go.sum index 72b8a53b..dacd50c2 100644 --- a/go.sum +++ b/go.sum @@ -468,6 +468,10 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM= go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.7.0 h1:8hPcgCg0rUJiKE6VWahRvjgLUrNl7rW2hffUEPKXVEM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.7.0/go.mod h1:K4GDXPY6TjUiwbOh+DkKaEdCF8y+lvMoM6SeAPyfCCM= +go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0= +go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU= go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJqC6o= go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -627,6 +631,7 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/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-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= From 79abec4fb99ef67fbb731cfd20f30c3d871cfd45 Mon Sep 17 00:00:00 2001 From: Deng Ming Date: Fri, 10 Jun 2022 18:48:21 +0800 Subject: [PATCH 3/4] fix 4975: graceful server listen the specific address --- CHANGELOG.md | 1 + server/web/grace/server.go | 1 - server/web/server.go | 3 ++- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ccd2470..6c632000 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # developing - [Fix issue 4961, `leafInfo.match()` use `path.join()` to deal with `wildcardValues`, which may lead to cross directory risk ](https://github.com/beego/beego/pull/4964) +- [Fix 4975: graceful server listen the specific address](https://github.com/beego/beego/pull/4979) # v2.0.3 - [upgrade redisgo to v1.8.8](https://github.com/beego/beego/pull/4872) - [fix prometheus CVE-2022-21698](https://github.com/beego/beego/pull/4878) diff --git a/server/web/grace/server.go b/server/web/grace/server.go index e9d36a00..c8a5f840 100644 --- a/server/web/grace/server.go +++ b/server/web/grace/server.go @@ -169,7 +169,6 @@ func (srv *Server) ServeTLS(ln net.Listener) error { } go srv.handleSignals() - log.Println(os.Getpid(), srv.Addr) return srv.internalServe(ln) } diff --git a/server/web/server.go b/server/web/server.go index 0011d455..fe4c6164 100644 --- a/server/web/server.go +++ b/server/web/server.go @@ -215,7 +215,8 @@ func (app *HttpServer) Run(addr string, mws ...MiddleWare) { if app.Cfg.Listen.ListenTCP4 { server.Network = "tcp4" } - ln, err := net.Listen(server.Network, app.Server.Addr) + ln, err := net.Listen(server.Network, server.Addr) + logs.Info("graceful http server Running on http://%s", server.Addr) if err != nil { logs.Critical("Listen for HTTP[graceful mode]: ", err) endRunning <- true From 41cc57dcf257f7445020d2451cfb3bec6137e2ab Mon Sep 17 00:00:00 2001 From: Deng Ming Date: Fri, 10 Jun 2022 21:23:00 +0800 Subject: [PATCH 4/4] fix 4976: make admin serve HTTP only --- CHANGELOG.md | 1 + server/web/admin.go | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c632000..f45ff708 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # developing - [Fix issue 4961, `leafInfo.match()` use `path.join()` to deal with `wildcardValues`, which may lead to cross directory risk ](https://github.com/beego/beego/pull/4964) - [Fix 4975: graceful server listen the specific address](https://github.com/beego/beego/pull/4979) +- [Fix 4976: make admin serve HTTP only](https://github.com/beego/beego/pull/4980) # v2.0.3 - [upgrade redisgo to v1.8.8](https://github.com/beego/beego/pull/4872) - [fix prometheus CVE-2022-21698](https://github.com/beego/beego/pull/4878) diff --git a/server/web/admin.go b/server/web/admin.go index 66ba3396..285f7feb 100644 --- a/server/web/admin.go +++ b/server/web/admin.go @@ -101,6 +101,7 @@ func registerAdmin() error { // copy config to avoid conflict adminCfg := *BConfig + adminCfg.Listen.EnableHTTPS = false beeAdminApp = &adminApp{ HttpServer: NewHttpServerWithCfg(&adminCfg), }