Skip to content

Commit

Permalink
revert context passing and added support for auth_provider plugin
Browse files Browse the repository at this point in the history
Signed-off-by: Jimil Desai <jimildesai42@gmail.com>
  • Loading branch information
jimil749 committed Aug 3, 2021
1 parent 5584e55 commit de75a3e
Show file tree
Hide file tree
Showing 11 changed files with 225 additions and 41 deletions.
41 changes: 34 additions & 7 deletions internal/grpc/services/authprovider/authprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ package authprovider
import (
"context"
"fmt"
"path/filepath"

provider "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1"
"github.com/cs3org/reva/pkg/appctx"
"github.com/cs3org/reva/pkg/auth"
"github.com/cs3org/reva/pkg/auth/manager/registry"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/plugin"
"github.com/cs3org/reva/pkg/rgrpc"
"github.com/cs3org/reva/pkg/rgrpc/status"
"github.com/mitchellh/mapstructure"
Expand All @@ -52,6 +54,7 @@ func (c *config) init() {
type service struct {
authmgr auth.Manager
conf *config
plugin *plugin.RevaPlugin
}

func parseConfig(m map[string]interface{}) (*config, error) {
Expand All @@ -64,14 +67,31 @@ func parseConfig(m map[string]interface{}) (*config, error) {
return c, nil
}

func getAuthManager(manager string, m map[string]map[string]interface{}) (auth.Manager, error) {
func getAuthManager(manager string, m map[string]map[string]interface{}) (auth.Manager, *plugin.RevaPlugin, error) {
if manager == "" {
return nil, errtypes.InternalError("authsvc: driver not configured for auth manager")
return nil, nil, errtypes.InternalError("authsvc: driver not configured for auth manager")
}
if f, ok := registry.NewFuncs[manager]; ok {
return f(m[manager])
p, err := plugin.Load("authprovider", manager)
if err == nil {
authManager, ok := p.Plugin.(auth.Manager)
if !ok {
return nil, nil, fmt.Errorf("could not assert the loaded plugin")
}
pluginConfig := filepath.Base(manager)
err = authManager.Configure(m[pluginConfig])
if err != nil {
return nil, nil, err
}
return authManager, p, nil
} else if _, ok := err.(errtypes.NotFound); ok {
if f, ok := registry.NewFuncs[manager]; ok {
authmgr, err := f(m[manager])
return authmgr, nil, err
}
} else {
return nil, nil, err
}
return nil, errtypes.NotFound(fmt.Sprintf("authsvc: driver %s not found for auth manager", manager))
return nil, nil, errtypes.NotFound(fmt.Sprintf("authsvc: driver %s not found for auth manager", manager))
}

// New returns a new AuthProviderServiceServer.
Expand All @@ -81,17 +101,24 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) {
return nil, err
}

authManager, err := getAuthManager(c.AuthManager, c.AuthManagers)
authManager, plug, err := getAuthManager(c.AuthManager, c.AuthManagers)
if err != nil {
return nil, err
}

svc := &service{conf: c, authmgr: authManager}
svc := &service{
conf: c,
authmgr: authManager,
plugin: plug,
}

return svc, nil
}

func (s *service) Close() error {
if s.plugin != nil {
s.plugin.Kill()
}
return nil
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ import (
authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1"
registry "github.com/cs3org/go-cs3apis/cs3/auth/registry/v1beta1"
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
"github.com/cs3org/reva/pkg/plugin"
)

// Manager is the interface to implement to authenticate users
type Manager interface {
plugin.Plugin
Authenticate(ctx context.Context, clientID, clientSecret string) (*user.User, map[string]*authpb.Scope, error)
}

Expand Down
12 changes: 10 additions & 2 deletions pkg/auth/manager/appauth/appauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,21 @@ type manager struct {
// New returns a new auth Manager.
func New(m map[string]interface{}) (auth.Manager, error) {
mgr := &manager{}
err := mapstructure.Decode(m, mgr)
err := mgr.Configure(m)
if err != nil {
return nil, errors.Wrap(err, "error decoding conf")
return nil, err
}
return mgr, nil
}

func (m *manager) Configure(ml map[string]interface{}) error {
err := mapstructure.Decode(ml, m)
if err != nil {
return errors.Wrap(err, "error decoding conf")
}
return nil
}

func (m *manager) Authenticate(ctx context.Context, username, password string) (*user.User, map[string]*authpb.Scope, error) {
gtw, err := pool.GetGatewayServiceClient(m.GatewayAddr)
if err != nil {
Expand Down
9 changes: 8 additions & 1 deletion pkg/auth/manager/demo/demo.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,15 @@ type Credentials struct {
// New returns a new auth Manager.
func New(m map[string]interface{}) (auth.Manager, error) {
// m not used
mgr := &manager{}
err := mgr.Configure(m)
return mgr, err
}

func (m *manager) Configure(ml map[string]interface{}) error {
creds := getCredentials()
return &manager{credentials: creds}, nil
m.credentials = creds
return nil
}

func (m *manager) Authenticate(ctx context.Context, clientID, clientSecret string) (*user.User, map[string]*authpb.Scope, error) {
Expand Down
4 changes: 4 additions & 0 deletions pkg/auth/manager/impersonator/impersonator.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ func New(c map[string]interface{}) (auth.Manager, error) {
return &mgr{}, nil
}

func (m *mgr) Configure(ml map[string]interface{}) error {
return nil
}

func (m *mgr) Authenticate(ctx context.Context, clientID, clientSecret string) (*user.User, map[string]*authpb.Scope, error) {
// allow passing in uid as <opaqueid>@<idp>
at := strings.LastIndex(clientID, "@")
Expand Down
21 changes: 14 additions & 7 deletions pkg/auth/manager/json/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,30 +79,37 @@ func parseConfig(m map[string]interface{}) (*config, error) {

// New returns a new auth Manager.
func New(m map[string]interface{}) (auth.Manager, error) {
c, err := parseConfig(m)
mgr := &manager{}
err := mgr.Configure(m)
if err != nil {
return nil, err
}
return mgr, nil
}

manager := &manager{credentials: map[string]*Credentials{}}
func (m *manager) Configure(ml map[string]interface{}) error {
c, err := parseConfig(ml)
if err != nil {
return err
}

m.credentials = map[string]*Credentials{}
f, err := ioutil.ReadFile(c.Users)
if err != nil {
return nil, err
return err
}

credentials := []*Credentials{}

err = json.Unmarshal(f, &credentials)
if err != nil {
return nil, err
return err
}

for _, c := range credentials {
manager.credentials[c.Username] = c
m.credentials[c.Username] = c
}

return manager, nil
return nil
}

func (m *manager) Authenticate(ctx context.Context, username string, secret string) (*user.User, map[string]*authpb.Scope, error) {
Expand Down
17 changes: 12 additions & 5 deletions pkg/auth/manager/ldap/ldap.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,19 @@ func parseConfig(m map[string]interface{}) (*config, error) {

// New returns an auth manager implementation that connects to a LDAP server to validate the user.
func New(m map[string]interface{}) (auth.Manager, error) {
c, err := parseConfig(m)
manager := &mgr{}
err := manager.Configure(m)
if err != nil {
return nil, err
}
return manager, nil
}

func (am *mgr) Configure(m map[string]interface{}) error {
c, err := parseConfig(m)
if err != nil {
return err
}

// backwards compatibility
if c.UserFilter != "" {
Expand All @@ -122,10 +131,8 @@ func New(m map[string]interface{}) (auth.Manager, error) {
}

c.GatewaySvc = sharedconf.GetGatewaySVC(c.GatewaySvc)

return &mgr{
c: c,
}, nil
am.c = c
return nil
}

func (am *mgr) Authenticate(ctx context.Context, clientID, clientSecret string) (*user.User, map[string]*authpb.Scope, error) {
Expand Down
15 changes: 12 additions & 3 deletions pkg/auth/manager/oidc/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,22 @@ func parseConfig(m map[string]interface{}) (*config, error) {

// New returns an auth manager implementation that verifies the oidc token and obtains the user claims.
func New(m map[string]interface{}) (auth.Manager, error) {
c, err := parseConfig(m)
manager := &mgr{}
err := manager.Configure(m)
if err != nil {
return nil, err
}
c.init()
return manager, nil
}

return &mgr{c: c}, nil
func (am *mgr) Configure(m map[string]interface{}) error {
c, err := parseConfig(m)
if err != nil {
return err
}
c.init()
am.c = c
return nil
}

// the clientID it would be empty as we only need to validate the clientSecret variable
Expand Down
15 changes: 11 additions & 4 deletions pkg/auth/manager/publicshares/publicshares.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,21 @@ func parseConfig(m map[string]interface{}) (*config, error) {

// New returns a new auth Manager.
func New(m map[string]interface{}) (auth.Manager, error) {
conf, err := parseConfig(m)
mgr := &manager{}
err := mgr.Configure(m)
if err != nil {
return nil, err
}
return mgr, nil
}

return &manager{
c: conf,
}, nil
func (m *manager) Configure(ml map[string]interface{}) error {
conf, err := parseConfig(ml)
if err != nil {
return err
}
m.c = conf
return nil
}

func (m *manager) Authenticate(ctx context.Context, token, secret string) (*user.User, map[string]*authpb.Scope, error) {
Expand Down
110 changes: 110 additions & 0 deletions pkg/auth/rpc_auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright 2018-2021 CERN
//
// 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.
//
// In applying this license, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

package auth

import (
"context"
"net/rpc"

authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1"
user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
"github.com/cs3org/reva/pkg/plugin"
hcplugin "github.com/hashicorp/go-plugin"
)

func init() {
plugin.Register("authprovider", &AuthProviderPlugin{})
}

// ProviderPlugin is the implementation of plugin.Plugin so we can serve/consume this.
type AuthProviderPlugin struct {
Impl Manager
}

// Server returns the RPC Server which serves the methods that the Client calls over net/rpc
func (p *AuthProviderPlugin) Server(*hcplugin.MuxBroker) (interface{}, error) {
return &RPCServer{Impl: p.Impl}, nil
}

// Client returns interface implementation for the plugin that communicates to the server end of the plugin
func (p *AuthProviderPlugin) Client(b *hcplugin.MuxBroker, c *rpc.Client) (interface{}, error) {
return &RPCClient{Client: c}, nil
}

// RPCClient is an implementation of Manager that talks over RPC.
type RPCClient struct{ Client *rpc.Client }

// ConfigureArg for RPC
type ConfigureArg struct {
Ml map[string]interface{}
}

// ConfigureReply for RPC
type ConfigureReply struct {
Err error
}

// Configure RPCClient configure method
func (m *RPCClient) Configure(ml map[string]interface{}) error {
args := ConfigureArg{Ml: ml}
resp := ConfigureReply{}
err := m.Client.Call("Plugin.Configure", args, &resp)
if err != nil {
return err
}
return resp.Err
}

type AuthenticateArgs struct {
ClientID string
ClientSecret string
}

type AuthenticateReply struct {
User *user.User
Auth map[string]*authpb.Scope
Error error
}

func (m *RPCClient) Authenticate(ctx context.Context, clientID, clientSecret string) (*user.User, map[string]*authpb.Scope, error) {
args := AuthenticateArgs{ClientID: clientID, ClientSecret: clientSecret}
reply := AuthenticateReply{}
err := m.Client.Call("Plugin.Authenticate", args, &reply)
if err != nil {
return nil, nil, err
}
return reply.User, reply.Auth, reply.Error
}

// RPCServer is the server that RPCClient talks to, conforming to the requirements of net/rpc
type RPCServer struct {
// This is the real implementation
Impl Manager
}

// Configure RPCServer Configure method
func (m *RPCServer) Configure(args ConfigureArg, resp *ConfigureReply) error {
resp.Err = m.Impl.Configure(args.Ml)
return nil
}

func (m *RPCServer) Authenticate(args AuthenticateArgs, resp *AuthenticateReply) error {
resp.User, resp.Auth, resp.Error = m.Impl.Authenticate(context.Background(), args.ClientID, args.ClientSecret)
return nil
}
Loading

0 comments on commit de75a3e

Please sign in to comment.