mirror of
https://github.com/owncloud/ocis
synced 2026-04-25 17:25:21 +02:00
feat: propagate GRPC metadata across go-micro services
The server handlers for go-micro reuse the data from reva so the propagation also works with reva services. Both reva and go-micro services will propagate the data correctly.
This commit is contained in:
66
ocis-pkg/service/grpc/handler/metadata/metadata.go
Normal file
66
ocis-pkg/service/grpc/handler/metadata/metadata.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package metadata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/owncloud/reva/v2/pkg/rgrpc"
|
||||
"go-micro.dev/v4/server"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
const (
|
||||
// Prefix used to auto propagate GRPC metadata keys across servers.
|
||||
// This is used in the NewHandlerWrapper and NewSubscriberWrapper, and
|
||||
// it's expected to work in go-micro services.
|
||||
// It needs to match the prefix used in reva for the same purpose.
|
||||
AutoPropPrefix = rgrpc.AutoPropPrefix
|
||||
)
|
||||
|
||||
// NewHandlerWrapper propagates the grpc metadata.
|
||||
func NewHandlerWrapper() server.HandlerWrapper {
|
||||
return func(h server.HandlerFunc) server.HandlerFunc {
|
||||
return func(ctx context.Context, req server.Request, rsp interface{}) error {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
md = metadata.MD{}
|
||||
}
|
||||
|
||||
pairs := make([]string, 0, md.Len()*2)
|
||||
for key, values := range md {
|
||||
if strings.HasPrefix(key, AutoPropPrefix) {
|
||||
for _, value := range values {
|
||||
pairs = append(pairs, key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newctx := metadata.AppendToOutgoingContext(ctx, pairs...)
|
||||
return h(newctx, req, rsp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NewSubscriberWrapper propagates the grpc metadata
|
||||
func NewSubscriberWrapper() server.SubscriberWrapper {
|
||||
return func(next server.SubscriberFunc) server.SubscriberFunc {
|
||||
return func(ctx context.Context, msg server.Message) error {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
md = metadata.MD{}
|
||||
}
|
||||
|
||||
pairs := make([]string, 0, md.Len()*2)
|
||||
for key, values := range md {
|
||||
if strings.HasPrefix(key, AutoPropPrefix) {
|
||||
for _, value := range values {
|
||||
pairs = append(pairs, key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newctx := metadata.AppendToOutgoingContext(ctx, pairs...)
|
||||
return next(newctx, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
ociscrypto "github.com/owncloud/ocis/v2/ocis-pkg/crypto"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/registry"
|
||||
ocismetadata "github.com/owncloud/ocis/v2/ocis-pkg/service/grpc/handler/metadata"
|
||||
)
|
||||
|
||||
// Service simply wraps the go-micro grpc service.
|
||||
@@ -64,6 +65,7 @@ func NewServiceWithClient(client client.Client, opts ...Option) (Service, error)
|
||||
mtracer.NewHandlerWrapper(
|
||||
mtracer.WithTraceProvider(sopts.TraceProvider),
|
||||
),
|
||||
ocismetadata.NewHandlerWrapper(),
|
||||
}
|
||||
if sopts.Logger.GetLevel() == zerolog.DebugLevel {
|
||||
handlerWrappers = append(handlerWrappers, LogHandler(&sopts.Logger))
|
||||
@@ -87,9 +89,10 @@ func NewServiceWithClient(client client.Client, opts ...Option) (Service, error)
|
||||
mtracer.WithTraceProvider(sopts.TraceProvider),
|
||||
)),
|
||||
micro.WrapHandler(handlerWrappers...),
|
||||
micro.WrapSubscriber(mtracer.NewSubscriberWrapper(
|
||||
mtracer.WithTraceProvider(sopts.TraceProvider),
|
||||
)),
|
||||
micro.WrapSubscriber(
|
||||
mtracer.NewSubscriberWrapper(mtracer.WithTraceProvider(sopts.TraceProvider)),
|
||||
ocismetadata.NewSubscriberWrapper(),
|
||||
),
|
||||
}
|
||||
|
||||
return Service{micro.NewService(mopts...)}, nil
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||
"github.com/owncloud/reva/v2/pkg/auth/manager/publicshares"
|
||||
"github.com/owncloud/reva/v2/pkg/rgrpc/todo/pool"
|
||||
)
|
||||
|
||||
@@ -91,6 +92,38 @@ func (a PublicShareAuthenticator) Authenticate(r *http.Request) (*http.Request,
|
||||
}
|
||||
}
|
||||
|
||||
client, err := a.RevaGatewaySelector.Next()
|
||||
if err != nil {
|
||||
a.Logger.Error().
|
||||
Err(err).
|
||||
Str("authenticator", "public_share").
|
||||
Str("public_share_token", shareToken).
|
||||
Str("path", r.URL.Path).
|
||||
Msg("could not select next gateway client")
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// we just need the reva access token, so we want to skip the brute force
|
||||
// protection in this case
|
||||
ctx := publicshares.MarkSkipAttemptContext(r.Context(), shareToken)
|
||||
authResp, err := client.Authenticate(ctx, &gateway.AuthenticateRequest{
|
||||
Type: authenticationType,
|
||||
ClientId: shareToken,
|
||||
ClientSecret: sharePassword,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
a.Logger.Error().
|
||||
Err(err).
|
||||
Str("authenticator", "public_share").
|
||||
Str("public_share_token", shareToken).
|
||||
Str("path", r.URL.Path).
|
||||
Msg("failed to authenticate request")
|
||||
return nil, false
|
||||
}
|
||||
|
||||
r.Header.Add(_headerRevaAccessToken, authResp.Token)
|
||||
|
||||
a.Logger.Debug().
|
||||
Str("authenticator", "public_share").
|
||||
Str("path", r.URL.Path).
|
||||
|
||||
Reference in New Issue
Block a user