Skip to content
Merged
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
10 changes: 10 additions & 0 deletions services/graph/pkg/service/v0/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/go-chi/chi/v5/middleware"
ldapv3 "github.com/go-ldap/ldap/v3"
"github.com/jellydator/ttlcache/v3"
"github.com/riandyrn/otelchi"
microstore "go-micro.dev/v4/store"

"github.com/opencloud-eu/reva/v2/pkg/events"
Expand All @@ -28,6 +29,7 @@ import (
"github.com/opencloud-eu/opencloud/pkg/registry"
"github.com/opencloud-eu/opencloud/pkg/roles"
"github.com/opencloud-eu/opencloud/pkg/service/grpc"
"github.com/opencloud-eu/opencloud/pkg/tracing"
settingssvc "github.com/opencloud-eu/opencloud/protogen/gen/opencloud/services/settings/v0"
"github.com/opencloud-eu/opencloud/services/graph/pkg/identity"
graphm "github.com/opencloud-eu/opencloud/services/graph/pkg/middleware"
Expand Down Expand Up @@ -128,6 +130,14 @@ func NewService(opts ...Option) (Graph, error) { //nolint:maintidx

m := chi.NewMux()
m.Use(options.Middleware...)
m.Use(
otelchi.Middleware(
"graph",
otelchi.WithChiRoutes(m),
otelchi.WithTracerProvider(options.TraceProvider),
otelchi.WithPropagators(tracing.GetPropagator()),
),
)

spacePropertiesCache := ttlcache.New(
ttlcache.WithTTL[string, interface{}](
Expand Down
8 changes: 6 additions & 2 deletions services/proxy/pkg/command/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,8 @@ func loadMiddlewares(logger log.Logger, cfg *config.Config,
}

return alice.New(
chimiddleware.RealIP,
chimiddleware.RequestID,
// first make sure we log all requests and redirect to https if necessary
otelhttp.NewMiddleware("proxy",
otelhttp.WithTracerProvider(traceProvider),
Expand All @@ -353,8 +355,6 @@ func loadMiddlewares(logger log.Logger, cfg *config.Config,
middleware.Tracer(traceProvider),
pkgmiddleware.TraceContext,
middleware.Instrumenter(metrics),
chimiddleware.RealIP,
chimiddleware.RequestID,
middleware.AccessLog(logger),
middleware.ContextLogger(logger),
middleware.HTTPSRedirect,
Expand All @@ -370,6 +370,7 @@ func loadMiddlewares(logger log.Logger, cfg *config.Config,
),
middleware.AccountResolver(
middleware.Logger(logger),
middleware.TraceProvider(traceProvider),
middleware.UserProvider(userProvider),
middleware.UserRoleAssigner(roleAssigner),
middleware.SkipUserInfo(cfg.OIDC.SkipUserInfo),
Expand All @@ -380,17 +381,20 @@ func loadMiddlewares(logger log.Logger, cfg *config.Config,
),
middleware.SelectorCookie(
middleware.Logger(logger),
middleware.TraceProvider(traceProvider),
middleware.PolicySelectorConfig(*cfg.PolicySelector),
),
middleware.Policies(
cfg.PoliciesMiddleware.Query,
middleware.Logger(logger),
middleware.TraceProvider(traceProvider),
middleware.WithRevaGatewaySelector(gatewaySelector),
middleware.PoliciesProviderService(policiesProviderClient),
),
// finally, trigger home creation when a user logs in
middleware.CreateHome(
middleware.Logger(logger),
middleware.TraceProvider(traceProvider),
middleware.WithRevaGatewaySelector(gatewaySelector),
middleware.RoleQuotas(cfg.RoleQuotas),
),
Expand Down
12 changes: 9 additions & 3 deletions services/proxy/pkg/middleware/account_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/opencloud-eu/opencloud/services/proxy/pkg/router"
"github.com/opencloud-eu/opencloud/services/proxy/pkg/user/backend"
"github.com/opencloud-eu/opencloud/services/proxy/pkg/userroles"
"go.opentelemetry.io/otel/trace"

cs3user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
"github.com/opencloud-eu/opencloud/pkg/log"
Expand All @@ -24,6 +25,7 @@ import (
func AccountResolver(optionSetters ...Option) func(next http.Handler) http.Handler {
options := newOptions(optionSetters...)
logger := options.Logger
tracer := getTraceProvider(options).Tracer("proxy.middleware.account_resolver")

lastGroupSyncCache := ttlcache.New(
ttlcache.WithTTL[string, struct{}](5*time.Minute),
Expand All @@ -35,6 +37,7 @@ func AccountResolver(optionSetters ...Option) func(next http.Handler) http.Handl
return &accountResolver{
next: next,
logger: logger,
tracer: tracer,
userProvider: options.UserProvider,
userOIDCClaim: options.UserOIDCClaim,
userCS3Claim: options.UserCS3Claim,
Expand All @@ -49,6 +52,7 @@ func AccountResolver(optionSetters ...Option) func(next http.Handler) http.Handl
type accountResolver struct {
next http.Handler
logger log.Logger
tracer trace.Tracer
userProvider backend.UserBackend
userRoleAssigner userroles.UserRoleAssigner
autoProvisionAccounts bool
Expand Down Expand Up @@ -98,12 +102,14 @@ func readUserIDClaim(path string, claims map[string]interface{}) (string, error)

// TODO do not use the context to store values: https://medium.com/@cep21/how-to-correctly-use-context-context-in-go-1-7-8f2c0fafdf39
func (m accountResolver) ServeHTTP(w http.ResponseWriter, req *http.Request) {
ctx := req.Context()
ctx, span := m.tracer.Start(req.Context(), fmt.Sprintf("%s %s", req.Method, req.URL.Path), trace.WithSpanKind(trace.SpanKindServer))
claims := oidc.FromContext(ctx)
user, ok := revactx.ContextGetUser(ctx)
token, hasToken := revactx.ContextGetToken(ctx)

req = req.WithContext(ctx)
defer span.End()
if claims == nil && !ok {
span.End()
m.next.ServeHTTP(w, req)
return
}
Expand Down Expand Up @@ -219,6 +225,6 @@ func (m accountResolver) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if !ri.SkipXAccessToken() {
req.Header.Set(revactx.TokenHeader, token)
}

span.End()
m.next.ServeHTTP(w, req)
}
11 changes: 8 additions & 3 deletions services/proxy/pkg/middleware/authentication.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/opencloud-eu/opencloud/services/proxy/pkg/router"
"github.com/opencloud-eu/opencloud/services/proxy/pkg/webdav"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"golang.org/x/text/cases"
"golang.org/x/text/language"
Expand Down Expand Up @@ -52,32 +53,36 @@ type Authenticator interface {
func Authentication(auths []Authenticator, opts ...Option) func(next http.Handler) http.Handler {
options := newOptions(opts...)
configureSupportedChallenges(options)
tracer := getTraceProvider(options).Tracer("proxy")
tracer := getTraceProvider(options).Tracer("proxy.middleware.authentication")

spanOpts := []trace.SpanStartOption{
trace.WithSpanKind(trace.SpanKindServer),
}

return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx, span := tracer.Start(r.Context(), fmt.Sprintf("%s %v", r.Method, r.URL.Path), spanOpts...)
defer span.End()
ctx, span := tracer.Start(r.Context(), fmt.Sprintf("%s %s", r.Method, r.URL.Path), spanOpts...)
r = r.WithContext(ctx)
defer span.End()

ri := router.ContextRoutingInfo(ctx)
if isOIDCTokenAuth(r) || ri.IsRouteUnprotected() || r.Method == "OPTIONS" {
// Either this is a request that does not need any authentication or
// the authentication for this request is handled by the IdP.
span.SetAttributes(attribute.Bool("routeunprotected", true))
span.End()
next.ServeHTTP(w, r)
return
}

for _, a := range auths {
if req, ok := a.Authenticate(r); ok {
span.End()
next.ServeHTTP(w, req)
return
}
}

if !isPublicPath(r.URL.Path) {
// Failed basic authentication attempts receive the Www-Authenticate header in the response
var touch bool
Expand Down
13 changes: 11 additions & 2 deletions services/proxy/pkg/middleware/create_home.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package middleware

import (
"fmt"
"net/http"
"strconv"

Expand All @@ -14,18 +15,21 @@ import (
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/status"
"github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool"
"github.com/opencloud-eu/reva/v2/pkg/utils"
"go.opentelemetry.io/otel/trace"
"google.golang.org/grpc/metadata"
)

// CreateHome provides a middleware which sends a CreateHome request to the reva gateway
func CreateHome(optionSetters ...Option) func(next http.Handler) http.Handler {
options := newOptions(optionSetters...)
logger := options.Logger
tracer := getTraceProvider(options).Tracer("proxy.middleware.create_home")

return func(next http.Handler) http.Handler {
return &createHome{
next: next,
logger: logger,
tracer: tracer,
revaGatewaySelector: options.RevaGatewaySelector,
roleQuotas: options.RoleQuotas,
}
Expand All @@ -35,12 +39,17 @@ func CreateHome(optionSetters ...Option) func(next http.Handler) http.Handler {
type createHome struct {
next http.Handler
logger log.Logger
tracer trace.Tracer
revaGatewaySelector pool.Selectable[gateway.GatewayAPIClient]
roleQuotas map[string]uint64
}

func (m createHome) ServeHTTP(w http.ResponseWriter, req *http.Request) {
ctx, span := m.tracer.Start(req.Context(), fmt.Sprintf("%s %s", req.Method, req.URL.Path), trace.WithSpanKind(trace.SpanKindServer))
req = req.WithContext(ctx)
defer span.End()
if !m.shouldServe(req) {
span.End()
m.next.ServeHTTP(w, req)
return
}
Expand All @@ -49,7 +58,7 @@ func (m createHome) ServeHTTP(w http.ResponseWriter, req *http.Request) {

// we need to pass the token to authenticate the CreateHome request.
//ctx := tokenpkg.ContextSetToken(r.Context(), token)
ctx := metadata.AppendToOutgoingContext(req.Context(), revactx.TokenHeader, token)
ctx = metadata.AppendToOutgoingContext(req.Context(), revactx.TokenHeader, token)

createHomeReq := &provider.CreateHomeRequest{}
u, ok := revactx.ContextGetUser(ctx)
Expand Down Expand Up @@ -79,7 +88,7 @@ func (m createHome) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
}
}

span.End()
m.next.ServeHTTP(w, req)
}

Expand Down
9 changes: 8 additions & 1 deletion services/proxy/pkg/middleware/policies.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package middleware

import (
"fmt"
"net/http"
"path"
"path/filepath"
Expand All @@ -11,6 +12,7 @@ import (
"github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/render"
tusd "github.com/tus/tusd/v2/pkg/handler"
"go.opentelemetry.io/otel/trace"
"google.golang.org/grpc/metadata"

revactx "github.com/opencloud-eu/reva/v2/pkg/ctx"
Expand Down Expand Up @@ -43,12 +45,17 @@ const DeniedMessage = "Operation denied due to security policies"
func Policies(qs string, opts ...Option) func(next http.Handler) http.Handler {
options := newOptions(opts...)
logger := options.Logger
tracer := getTraceProvider(options).Tracer("proxy.middleware.policies")
gatewaySelector := options.RevaGatewaySelector
policiesProviderClient := options.PoliciesProviderService

return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx, span := tracer.Start(r.Context(), fmt.Sprintf("%s %s", r.Method, r.URL.Path), trace.WithSpanKind(trace.SpanKindServer))
r = r.WithContext(ctx)
defer span.End()
if qs == "" {
span.End()
next.ServeHTTP(w, r)
return
}
Expand Down Expand Up @@ -134,7 +141,7 @@ func Policies(qs string, opts ...Option) func(next http.Handler) http.Handler {
RenderError(w, r, req, http.StatusForbidden, DeniedMessage)
return
}

span.End()
next.ServeHTTP(w, r)
})
}
Expand Down
10 changes: 10 additions & 0 deletions services/proxy/pkg/middleware/selector_cookie.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
package middleware

import (
"fmt"
"net/http"

"github.com/opencloud-eu/opencloud/pkg/log"
"github.com/opencloud-eu/opencloud/pkg/oidc"
"github.com/opencloud-eu/opencloud/services/proxy/pkg/config"
"github.com/opencloud-eu/opencloud/services/proxy/pkg/proxy/policy"
"go.opentelemetry.io/otel/trace"
)

// SelectorCookie provides a middleware which
func SelectorCookie(optionSetters ...Option) func(next http.Handler) http.Handler {
options := newOptions(optionSetters...)
logger := options.Logger
policySelector := options.PolicySelector
tracer := getTraceProvider(options).Tracer("proxy.middleware.selector_cookie")

return func(next http.Handler) http.Handler {
return &selectorCookie{
next: next,
logger: logger,
tracer: tracer,
policySelector: policySelector,
}
}
Expand All @@ -27,12 +31,17 @@ func SelectorCookie(optionSetters ...Option) func(next http.Handler) http.Handle
type selectorCookie struct {
next http.Handler
logger log.Logger
tracer trace.Tracer
policySelector config.PolicySelector
}

func (m selectorCookie) ServeHTTP(w http.ResponseWriter, req *http.Request) {
ctx, span := m.tracer.Start(req.Context(), fmt.Sprintf("%s %s", req.Method, req.URL.Path), trace.WithSpanKind(trace.SpanKindServer))
req = req.WithContext(ctx)
defer span.End()
if m.policySelector.Regex == nil && m.policySelector.Claims == nil {
// only set selector cookie for regex and claim selectors
span.End()
m.next.ServeHTTP(w, req)
return
}
Expand Down Expand Up @@ -65,5 +74,6 @@ func (m selectorCookie) ServeHTTP(w http.ResponseWriter, req *http.Request) {
http.SetCookie(w, &cookie)
}

defer span.End()
m.next.ServeHTTP(w, req)
}
22 changes: 2 additions & 20 deletions services/proxy/pkg/middleware/tracing.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package middleware

import (
"fmt"
"net/http"

chimiddleware "github.com/go-chi/chi/v5/middleware"
pkgtrace "github.com/opencloud-eu/opencloud/pkg/tracing"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"
)

Expand All @@ -27,27 +24,12 @@ type tracer struct {
}

func (m tracer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var (
ctx = r.Context()
span trace.Span
)

ctx = pkgtrace.Propagator.Extract(ctx, propagation.HeaderCarrier(r.Header))

tracer := m.traceProvider.Tracer("proxy")
spanOpts := []trace.SpanStartOption{
trace.WithSpanKind(trace.SpanKindServer),
}
ctx, span = tracer.Start(ctx, fmt.Sprintf("%s %v", r.Method, r.URL.Path), spanOpts...)
defer span.End()

span := trace.SpanFromContext(r.Context())
span.SetAttributes(
attribute.KeyValue{
Key: "x-request-id",
Value: attribute.StringValue(chimiddleware.GetReqID(r.Context())),
})

pkgtrace.Propagator.Inject(ctx, propagation.HeaderCarrier(r.Header))

m.next.ServeHTTP(w, r.WithContext(ctx))
m.next.ServeHTTP(w, r)
}