Skip to content

Commit

Permalink
Functionality to map home directory to different storage providers (#…
Browse files Browse the repository at this point in the history
…1142)

* Functionality to map home directory to different storage providers

* Default to /home rule if no match is found

* Replace layouts only for home paths

* Don't log client secrets
  • Loading branch information
ishank011 authored Sep 18, 2020
1 parent 5e9de81 commit ecef02d
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 21 deletions.
7 changes: 7 additions & 0 deletions changelog/unreleased/home-sp-mapping.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Enhancement: Functionality to map home directory to different storage providers

We hardcode the home path for all users to /home. This forbids redirecting
requests for different users to multiple storage providers. This PR provides the
option to map the home directories of different users using user attributes.

https://github.com/cs3org/reva/pull/1142
25 changes: 22 additions & 3 deletions internal/grpc/interceptors/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,16 @@ func NewUnary(m map[string]interface{}, unprotected []string) (grpc.UnaryServerI
if utils.Skip(info.FullMethod, unprotected) {
span.AddAttributes(trace.BoolAttribute("auth_enabled", false))
log.Debug().Str("method", info.FullMethod).Msg("skipping auth")

// If a token is present, set it anyway, as we might need the user info
// to decide the storage provider.
tkn, ok := token.ContextGetToken(ctx)
if ok {
u, err := tokenManager.DismantleToken(ctx, tkn)
if err == nil {
ctx = user.ContextSetUser(ctx, u)
}
}
return handler(ctx, req)
}

Expand Down Expand Up @@ -111,7 +121,6 @@ func NewUnary(m map[string]interface{}, unprotected []string) (grpc.UnaryServerI
span.AddAttributes(trace.StringAttribute("user", u.String()), trace.StringAttribute("token", tkn))

ctx = user.ContextSetUser(ctx, u)
ctx = token.ContextSetToken(ctx, tkn)
return handler(ctx, req)
}
return interceptor, nil
Expand Down Expand Up @@ -145,6 +154,18 @@ func NewStream(m map[string]interface{}, unprotected []string) (grpc.StreamServe

if utils.Skip(info.FullMethod, unprotected) {
log.Debug().Str("method", info.FullMethod).Msg("skipping auth")

// If a token is present, set it anyway, as we might need the user info
// to decide the storage provider.
tkn, ok := token.ContextGetToken(ctx)
if ok {
u, err := tokenManager.DismantleToken(ctx, tkn)
if err == nil {
ctx = user.ContextSetUser(ctx, u)
ss = newWrappedServerStream(ctx, ss)
}
}

return handler(srv, ss)
}

Expand All @@ -170,8 +191,6 @@ func NewStream(m map[string]interface{}, unprotected []string) (grpc.StreamServe

// store user and core access token in context.
ctx = user.ContextSetUser(ctx, u)
ctx = token.ContextSetToken(ctx, tkn)

wrapped := newWrappedServerStream(ctx, ss)
return handler(srv, wrapped)
}
Expand Down
5 changes: 3 additions & 2 deletions internal/grpc/services/gateway/authprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/cs3org/reva/pkg/rgrpc/status"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
tokenpkg "github.com/cs3org/reva/pkg/token"
userpkg "github.com/cs3org/reva/pkg/user"
"github.com/pkg/errors"
"google.golang.org/grpc/metadata"
)
Expand Down Expand Up @@ -108,11 +109,11 @@ func (s *svc) Authenticate(ctx context.Context, req *gateway.AuthenticateRequest
// we need to pass the token to authenticate the CreateHome request.
// TODO(labkode): appending to existing context will not pass the token.
ctx = tokenpkg.ContextSetToken(ctx, token)
ctx = userpkg.ContextSetUser(ctx, user)
ctx = metadata.AppendToOutgoingContext(ctx, tokenpkg.TokenHeader, token) // TODO(jfd): hardcoded metadata key. use PerRPCCredentials?

// create home directory
createHomeReq := &storageprovider.CreateHomeRequest{}
createHomeRes, err := s.CreateHome(ctx, createHomeReq)
createHomeRes, err := s.CreateHome(ctx, &storageprovider.CreateHomeRequest{})
if err != nil {
log.Err(err).Msg("error calling CreateHome")
return &gateway.AuthenticateResponse{
Expand Down
1 change: 1 addition & 0 deletions internal/grpc/services/gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type config struct {
TokenManager string `mapstructure:"token_manager"`
// ShareFolder is the location where to create shares in the recipient's storage provider.
ShareFolder string `mapstructure:"share_folder"`
HomeMapping string `mapstructure:"home_mapping"`
TokenManagers map[string]map[string]interface{} `mapstructure:"token_managers"`
}

Expand Down
41 changes: 33 additions & 8 deletions internal/grpc/services/gateway/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import (
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/rgrpc/status"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/pkg/storage/utils/templates"
"github.com/cs3org/reva/pkg/user"
"github.com/dgrijalva/jwt-go"
"github.com/pkg/errors"
)
Expand Down Expand Up @@ -1795,32 +1797,55 @@ func (s *svc) getStorageProviderClient(_ context.Context, p *registry.ProviderIn
}

func (s *svc) findProvider(ctx context.Context, ref *provider.Reference) (*registry.ProviderInfo, error) {
c, err := pool.GetStorageRegistryClient(s.c.StorageRegistryEndpoint)
home, err := s.GetHome(ctx, &provider.GetHomeRequest{})
if err != nil {
err = errors.Wrap(err, "gateway: error getting storage registry client")
return nil, err
}
if strings.HasPrefix(ref.GetPath(), home.Path) && s.c.HomeMapping != "" {
if u, ok := user.ContextGetUser(ctx); ok {
layout := templates.WithUser(u, s.c.HomeMapping)
newRef := &provider.Reference{
Spec: &provider.Reference_Path{
Path: path.Join(layout, strings.TrimPrefix(ref.GetPath(), home.Path)),
},
}
res, err := s.getStorageProvider(ctx, newRef)
if err != nil {
// if we get a NotFound error, default to the original reference
if _, ok := err.(errtypes.IsNotFound); !ok {
return nil, err
}
} else {
return res, nil
}
}
}
return s.getStorageProvider(ctx, ref)
}

func (s *svc) getStorageProvider(ctx context.Context, ref *provider.Reference) (*registry.ProviderInfo, error) {
c, err := pool.GetStorageRegistryClient(s.c.StorageRegistryEndpoint)
if err != nil {
return nil, errors.Wrap(err, "gateway: error getting storage registry client")
}

res, err := c.GetStorageProvider(ctx, &registry.GetStorageProviderRequest{
Ref: ref,
})

if err != nil {
err = errors.Wrap(err, "gateway: error calling GetStorageProvider")
return nil, err
return nil, errors.Wrap(err, "gateway: error calling GetStorageProvider")
}

if res.Status.Code != rpc.Code_CODE_OK {
if res.Status.Code == rpc.Code_CODE_NOT_FOUND {
return nil, errtypes.NotFound("gateway: storage provider not found for reference:" + ref.String())
}
err := status.NewErrorFromCode(res.Status.Code, "gateway")
return nil, err
return nil, status.NewErrorFromCode(res.Status.Code, "gateway")
}

if res.Provider == nil {
err := errors.New("gateway: provider is nil")
return nil, err
return nil, errors.New("gateway: provider is nil")
}

return res.Provider, nil
Expand Down
7 changes: 2 additions & 5 deletions internal/grpc/services/gateway/usershareprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,10 +381,7 @@ func (s *svc) createReference(ctx context.Context, resourceID *provider.Resource
return status.NewInternal(ctx, err, "error updating received share"), nil
}

fileInfo := statRes.Info

homeReq := &provider.GetHomeRequest{}
homeRes, err := s.GetHome(ctx, homeReq)
homeRes, err := s.GetHome(ctx, &provider.GetHomeRequest{})
if err != nil {
err := errors.Wrap(err, "gateway: error calling GetHome")
return status.NewInternal(ctx, err, "error updating received share"), nil
Expand All @@ -400,7 +397,7 @@ func (s *svc) createReference(ctx context.Context, resourceID *provider.Resource
// It is the responsibility of the gateway to resolve these references and merge the response back
// from the main request.
// TODO(labkode): the name of the share should be the filename it points to by default.
refPath := path.Join(homeRes.Path, s.c.ShareFolder, path.Base(fileInfo.Path))
refPath := path.Join(homeRes.Path, s.c.ShareFolder, path.Base(statRes.Info.Path))
log.Info().Msg("mount path will be:" + refPath)

createRefReq := &provider.CreateReferenceRequest{
Expand Down
5 changes: 2 additions & 3 deletions internal/http/interceptors/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,7 @@ func New(m map[string]interface{}, unprotected []string) (global.Middleware, err
log.Debug().Err(err).Msg("error retrieving credentials")
}
if creds != nil {
log.Debug().Msgf("credentials obtained from credential strategy: %+v", creds)

log.Debug().Msgf("credentials obtained from credential strategy: type: %s, client_id: %s", creds.Type, creds.ClientID)
break
}
}
Expand All @@ -191,7 +190,7 @@ func New(m map[string]interface{}, unprotected []string) (global.Middleware, err
ClientSecret: creds.ClientSecret,
}

log.Debug().Msgf("AuthenticateRequest: %+v against %s", req, conf.GatewaySvc)
log.Debug().Msgf("AuthenticateRequest: type: %s, client_id: %s against %s", req.Type, req.ClientId, conf.GatewaySvc)

client, err := pool.GetGatewayServiceClient(conf.GatewaySvc)
if err != nil {
Expand Down

0 comments on commit ecef02d

Please sign in to comment.