Skip to content

Commit

Permalink
refact: add permssion check (#4448)
Browse files Browse the repository at this point in the history
* refact:  add permssion check
1. go-jsonrpc support field reflect
2. go-ipfs-cmds support auth check in hanlder
3. venus client support  dynamically specifies whether to expose to external calls
4. venus client code can generate by tools
  • Loading branch information
Rennbon authored May 24, 2021
1 parent 39a41a3 commit 95d0277
Show file tree
Hide file tree
Showing 117 changed files with 2,393 additions and 1,617 deletions.
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,11 @@ clean:
rm ./venus

rm -rf ./extern/filecoin-ffi
rm -rf ./extern/test-vectors
rm -rf ./extern/test-vectors

gen:
go run ./tools/gen/api/proxygen.go
gofmt -s -l -w ./app/client/client_gen.go
goimports -l -w ./app/client/client_gen.go


325 changes: 0 additions & 325 deletions app/client/client.go

This file was deleted.

256 changes: 256 additions & 0 deletions app/client/client_gen.go

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions app/client/funcrule/permissioned.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package funcrule

import (
"context"
"github.com/filecoin-project/go-jsonrpc/auth"
"golang.org/x/xerrors"
"reflect"
)

type MethodName = string

// Rule[perm:admin,ignore:true]
// Used by Client to generate rule comments
type Rule struct {
Perm auth.Permission
Ignore bool
}

var AllPermissions = []auth.Permission{"read", "write", "sign", "admin"}
var defaultPerms = []auth.Permission{"read"}

func defaultRule() *Rule {
return &Rule{
Perm: "read",
}
}

//permissionVerify the scheduler between API and internal business
func PermissionProxy(in interface{}, out interface{}) {
ra := reflect.ValueOf(in)
rint := reflect.ValueOf(out).Elem()
for i := 0; i < ra.NumMethod(); i++ {
methodName := ra.Type().Method(i).Name
field, exists := rint.Type().FieldByName(methodName)
if !exists {
//log.Printf("exclude method %s from fullNode", methodName)
continue
}

requiredPerm := field.Tag.Get("perm")
if requiredPerm == "" {
panic("missing 'perm' tag on " + field.Name) // ok
}
curule := defaultRule()
curule.Perm = requiredPerm

fn := ra.Method(i)
rint.FieldByName(methodName).Set(reflect.MakeFunc(field.Type, func(args []reflect.Value) (results []reflect.Value) {
ctx := args[0].Interface().(context.Context)
errNum := 0
if !auth.HasPerm(ctx, defaultPerms, curule.Perm) {
errNum++
goto ABORT
}
return fn.Call(args)
ABORT:
err := xerrors.Errorf("missing permission to invoke '%s'", methodName)
if errNum&1 == 1 {
err = xerrors.Errorf("%s (need '%s')", err, curule.Perm)
}
rerr := reflect.ValueOf(&err).Elem()
if fn.Type().NumOut() == 2 {
return []reflect.Value{
reflect.Zero(fn.Type().Out(0)),
rerr,
}
}
return []reflect.Value{rerr}
}))
}
}
16 changes: 8 additions & 8 deletions app/client/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,28 +46,28 @@ func getVenusClientInfo() (string, http.Header, error) {
return addr, headers, nil
}

func NewFullNode(ctx context.Context) (FullNode, jsonrpc.ClientCloser, error) {
func NewFullNode(ctx context.Context) (FullNodeStruct, jsonrpc.ClientCloser, error) {
addr, headers, err := getVenusClientInfo()
if err != nil {
return FullNode{}, nil, err
return FullNodeStruct{}, nil, err
}
node := FullNode{}
node := FullNodeStruct{}
closer, err := jsonrpc.NewClient(ctx, addr, "Filecoin", &node, headers)
if err != nil {
return FullNode{}, nil, err
return FullNodeStruct{}, nil, err
}
return node, closer, nil
}

func NewMiningAPINode(ctx context.Context) (MiningAPI, jsonrpc.ClientCloser, error) {
func NewMiningAPINode(ctx context.Context) (IMiningStruct, jsonrpc.ClientCloser, error) {
addr, headers, err := getVenusClientInfo()
if err != nil {
return MiningAPI{}, nil, err
return IMiningStruct{}, nil, err
}
node := MiningAPI{}
node := IMiningStruct{}
closer, err := jsonrpc.NewClient(ctx, addr, "Filecoin", &node, headers)
if err != nil {
return MiningAPI{}, nil, err
return IMiningStruct{}, nil, err
}
return node, closer, nil
}
14 changes: 7 additions & 7 deletions app/node/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"github.com/filecoin-project/venus/pkg/repo"
"github.com/filecoin-project/venus/pkg/specactors/policy"
"github.com/filecoin-project/venus/pkg/statemanger"
"github.com/filecoin-project/venus/pkg/util"
"github.com/filecoin-project/venus/pkg/util/ffiwrapper"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p"
Expand Down Expand Up @@ -289,11 +288,12 @@ func (b *Builder) build(ctx context.Context) (*Node, error) {

stmgr := statemanger.NewStateMangerAPI(nd.chain.ChainReader, nd.syncer.Consensus)
mgrps := &paychmgr.ManagerParams{
MPoolAPI: nd.mpool.API(),
ChainAPI: nd.chain.API(),
Protocol: nd.syncer.Consensus,
SM: stmgr,
DS: b.repo.PaychDatastore(),
MPoolAPI: nd.mpool.API(),
ChainAPI: nd.chain.API(),
Protocol: nd.syncer.Consensus,
SM: stmgr,
DS: b.repo.PaychDatastore(),
WalletAPI: nd.wallet.API(),
}
nd.paychan = paych.NewPaychSubmodule(ctx, mgrps)
nd.market = market.NewMarketModule(nd.chain.API(), stmgr)
Expand All @@ -315,7 +315,7 @@ func (b *Builder) build(ctx context.Context) (*Node, error) {
nd.jwtCli = client
}

apiBuilder := util.NewBuiler()
apiBuilder := NewBuilder()
apiBuilder.NameSpace("Filecoin")
err = apiBuilder.AddServices(nd.configModule,
nd.blockstore,
Expand Down
47 changes: 17 additions & 30 deletions app/node/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,31 @@ package node

import (
"context"
"github.com/filecoin-project/venus/app/submodule/market"
"github.com/filecoin-project/venus/app/submodule/multisig"
"github.com/filecoin-project/venus/app/submodule/paych"

"github.com/filecoin-project/venus/app/submodule/apiface"
cmds "github.com/ipfs/go-ipfs-cmds"

"github.com/filecoin-project/venus/app/submodule/blockservice"
"github.com/filecoin-project/venus/app/submodule/blockstore"
"github.com/filecoin-project/venus/app/submodule/chain"
"github.com/filecoin-project/venus/app/submodule/config"
"github.com/filecoin-project/venus/app/submodule/discovery"
"github.com/filecoin-project/venus/app/submodule/mining"
"github.com/filecoin-project/venus/app/submodule/mpool"
"github.com/filecoin-project/venus/app/submodule/network"
"github.com/filecoin-project/venus/app/submodule/storagenetworking"
"github.com/filecoin-project/venus/app/submodule/syncer"
"github.com/filecoin-project/venus/app/submodule/wallet"
)

// Env is the environment for command API handlers.
type Env struct {
ctx context.Context
InspectorAPI *Inspector
BlockServiceAPI *blockservice.BlockServiceAPI
BlockStoreAPI *blockstore.BlockstoreAPI
ChainAPI *chain.ChainAPI
ConfigAPI *config.ConfigAPI
DiscoveryAPI *discovery.DiscoveryAPI
NetworkAPI *network.NetworkAPI
StorageNetworkingAPI *storagenetworking.StorageNetworkingAPI
SyncerAPI *syncer.SyncerAPI
WalletAPI *wallet.WalletAPI
MingingAPI *mining.MiningAPI
MessagePoolAPI *mpool.MessagePoolAPI

MultiSigAPI multisig.IMultiSig
MarketAPI market.IMarket
PaychAPI paych.IPaychan
InspectorAPI IInspector
BlockServiceAPI apiface.IBlockService
BlockStoreAPI apiface.IBlockStore
ChainAPI apiface.IChain
ConfigAPI apiface.IConfig
DiscoveryAPI apiface.IDiscovery
NetworkAPI apiface.INetwork
StorageNetworkingAPI storagenetworking.IStorageNetworking
SyncerAPI apiface.ISyncer
WalletAPI apiface.IWallet
MingingAPI apiface.IMining
MessagePoolAPI apiface.IMessagePool

MultiSigAPI apiface.IMultiSig
MarketAPI apiface.IMarket
PaychAPI apiface.IPaychan
}

var _ cmds.Environment = (*Env)(nil)
Expand Down
29 changes: 20 additions & 9 deletions app/node/inspector_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,26 @@ import (
"runtime"
)

type IInspector interface {
Runtime() *RuntimeInfo
Memory() (*MemoryInfo, error)
Config() *config.Config
Disk() (*DiskInfo, error)
FilecoinVersion() string
Environment() *EnvironmentInfo
}

var _ IInspector = &inspector{}

// NewInspectorAPI returns a `Inspector` used to inspect the venus node.
func NewInspectorAPI(r repo.Repo) *Inspector {
return &Inspector{
func NewInspectorAPI(r repo.Repo) IInspector {
return &inspector{
repo: r,
}
}

// Inspector contains information used to inspect the venus node.
type Inspector struct {
type inspector struct {
repo repo.Repo
}

Expand Down Expand Up @@ -65,7 +76,7 @@ type MemoryInfo struct {
}

// Runtime returns infrormation about the golang runtime.
func (g *Inspector) Runtime() *RuntimeInfo {
func (g *inspector) Runtime() *RuntimeInfo {
return &RuntimeInfo{
OS: runtime.GOOS,
Arch: runtime.GOARCH,
Expand All @@ -79,7 +90,7 @@ func (g *Inspector) Runtime() *RuntimeInfo {
}

// Environment returns information about the environment filecoin is running in.
func (g *Inspector) Environment() *EnvironmentInfo {
func (g *inspector) Environment() *EnvironmentInfo {
return &EnvironmentInfo{
FilAPI: os.Getenv("FIL_API"),
FilPath: os.Getenv("FIL_PATH"),
Expand All @@ -88,7 +99,7 @@ func (g *Inspector) Environment() *EnvironmentInfo {
}

// Disk return information about filesystem the filecoin nodes repo is on.
func (g *Inspector) Disk() (*DiskInfo, error) {
func (g *inspector) Disk() (*DiskInfo, error) {
fsr, ok := g.repo.(*repo.FSRepo)
if !ok {
// we are using a in memory repo
Expand Down Expand Up @@ -117,7 +128,7 @@ func (g *Inspector) Disk() (*DiskInfo, error) {
}

// Memory return information about system meory usage.
func (g *Inspector) Memory() (*MemoryInfo, error) {
func (g *inspector) Memory() (*MemoryInfo, error) {
meminfo, err := sysi.MemoryInfo()
if err != nil {
return nil, err
Expand All @@ -129,11 +140,11 @@ func (g *Inspector) Memory() (*MemoryInfo, error) {
}

// configModule return the current config values of the filecoin node.
func (g *Inspector) Config() *config.Config {
func (g *inspector) Config() *config.Config {
return g.repo.Config()
}

// FilecoinVersion returns the version of venus.
func (g *Inspector) FilecoinVersion() string {
func (g *inspector) FilecoinVersion() string {
return fmt.Sprintf("%s %s", flags.GitTag, flags.GitCommit)
}
3 changes: 1 addition & 2 deletions app/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,8 +217,6 @@ func (node *Node) Stop(ctx context.Context) {
if err := node.repo.Close(); err != nil {
fmt.Printf("error closing repo: %s\n", err)
}

fmt.Println("stopping filecoin :(")
}

func (node *Node) RunRPCAndWait(ctx context.Context, rootCmdDaemon *cmds.Command, ready chan interface{}) error {
Expand Down Expand Up @@ -294,6 +292,7 @@ func (node *Node) runRestfulAPI(ctx context.Context, handler *http.ServeMux, roo
cfg.SetAllowedOrigins(apiConfig.AccessControlAllowOrigin...)
cfg.SetAllowedMethods(apiConfig.AccessControlAllowMethods...)
cfg.SetAllowCredentials(apiConfig.AccessControlAllowCredentials)
cfg.AppendAllowHeaders("Authorization")

handler.Handle(APIPrefix+"/", cmdhttp.NewHandler(servenv, rootCmdDaemon, cfg))
return nil
Expand Down
20 changes: 11 additions & 9 deletions pkg/util/apibuilder.go → app/node/rpc.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package util
package node

import (
"github.com/filecoin-project/go-jsonrpc"
xerrors "github.com/pkg/errors"
"github.com/filecoin-project/venus/app/client"
"github.com/filecoin-project/venus/app/client/funcrule"
"golang.org/x/xerrors"
"reflect"
)

Expand All @@ -14,7 +16,7 @@ type RPCBuilder struct {
apiStruct []interface{}
}

func NewBuiler() *RPCBuilder {
func NewBuilder() *RPCBuilder {
return &RPCBuilder{}
}

Expand Down Expand Up @@ -55,17 +57,17 @@ func (builder *RPCBuilder) AddService(service RPCService) error {
builder.apiStruct = append(builder.apiStruct, apiImpl.Interface())
}
}

return nil
}

func (builder *RPCBuilder) Build() *jsonrpc.RPCServer {
server := jsonrpc.NewServer()
server := jsonrpc.NewServer(jsonrpc.WithProxyBind(jsonrpc.PBField))
var fullNode client.FullNodeStruct
for _, apiStruct := range builder.apiStruct {
funcrule.PermissionProxy(apiStruct, &fullNode)
}
for _, nameSpace := range builder.namespace {
for _, apiStruct := range builder.apiStruct {
//fmt.Println("JSON RPC register:", nameSpace)
server.Register(nameSpace, apiStruct)
}
server.Register(nameSpace, &fullNode)
}
return server
}
Loading

0 comments on commit 95d0277

Please sign in to comment.