Skip to content

Commit 95d0277

Browse files
authored
refact: add permssion check (#4448)
* 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
1 parent 39a41a3 commit 95d0277

File tree

117 files changed

+2393
-1617
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

117 files changed

+2393
-1617
lines changed

Makefile

+8-1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,11 @@ clean:
1616
rm ./venus
1717

1818
rm -rf ./extern/filecoin-ffi
19-
rm -rf ./extern/test-vectors
19+
rm -rf ./extern/test-vectors
20+
21+
gen:
22+
go run ./tools/gen/api/proxygen.go
23+
gofmt -s -l -w ./app/client/client_gen.go
24+
goimports -l -w ./app/client/client_gen.go
25+
26+

app/client/client.go

-325
This file was deleted.

app/client/client_gen.go

+256
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/client/funcrule/permissioned.go

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package funcrule
2+
3+
import (
4+
"context"
5+
"github.com/filecoin-project/go-jsonrpc/auth"
6+
"golang.org/x/xerrors"
7+
"reflect"
8+
)
9+
10+
type MethodName = string
11+
12+
// Rule[perm:admin,ignore:true]
13+
// Used by Client to generate rule comments
14+
type Rule struct {
15+
Perm auth.Permission
16+
Ignore bool
17+
}
18+
19+
var AllPermissions = []auth.Permission{"read", "write", "sign", "admin"}
20+
var defaultPerms = []auth.Permission{"read"}
21+
22+
func defaultRule() *Rule {
23+
return &Rule{
24+
Perm: "read",
25+
}
26+
}
27+
28+
//permissionVerify the scheduler between API and internal business
29+
func PermissionProxy(in interface{}, out interface{}) {
30+
ra := reflect.ValueOf(in)
31+
rint := reflect.ValueOf(out).Elem()
32+
for i := 0; i < ra.NumMethod(); i++ {
33+
methodName := ra.Type().Method(i).Name
34+
field, exists := rint.Type().FieldByName(methodName)
35+
if !exists {
36+
//log.Printf("exclude method %s from fullNode", methodName)
37+
continue
38+
}
39+
40+
requiredPerm := field.Tag.Get("perm")
41+
if requiredPerm == "" {
42+
panic("missing 'perm' tag on " + field.Name) // ok
43+
}
44+
curule := defaultRule()
45+
curule.Perm = requiredPerm
46+
47+
fn := ra.Method(i)
48+
rint.FieldByName(methodName).Set(reflect.MakeFunc(field.Type, func(args []reflect.Value) (results []reflect.Value) {
49+
ctx := args[0].Interface().(context.Context)
50+
errNum := 0
51+
if !auth.HasPerm(ctx, defaultPerms, curule.Perm) {
52+
errNum++
53+
goto ABORT
54+
}
55+
return fn.Call(args)
56+
ABORT:
57+
err := xerrors.Errorf("missing permission to invoke '%s'", methodName)
58+
if errNum&1 == 1 {
59+
err = xerrors.Errorf("%s (need '%s')", err, curule.Perm)
60+
}
61+
rerr := reflect.ValueOf(&err).Elem()
62+
if fn.Type().NumOut() == 2 {
63+
return []reflect.Value{
64+
reflect.Zero(fn.Type().Out(0)),
65+
rerr,
66+
}
67+
}
68+
return []reflect.Value{rerr}
69+
}))
70+
}
71+
}

app/client/node.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -46,28 +46,28 @@ func getVenusClientInfo() (string, http.Header, error) {
4646
return addr, headers, nil
4747
}
4848

49-
func NewFullNode(ctx context.Context) (FullNode, jsonrpc.ClientCloser, error) {
49+
func NewFullNode(ctx context.Context) (FullNodeStruct, jsonrpc.ClientCloser, error) {
5050
addr, headers, err := getVenusClientInfo()
5151
if err != nil {
52-
return FullNode{}, nil, err
52+
return FullNodeStruct{}, nil, err
5353
}
54-
node := FullNode{}
54+
node := FullNodeStruct{}
5555
closer, err := jsonrpc.NewClient(ctx, addr, "Filecoin", &node, headers)
5656
if err != nil {
57-
return FullNode{}, nil, err
57+
return FullNodeStruct{}, nil, err
5858
}
5959
return node, closer, nil
6060
}
6161

62-
func NewMiningAPINode(ctx context.Context) (MiningAPI, jsonrpc.ClientCloser, error) {
62+
func NewMiningAPINode(ctx context.Context) (IMiningStruct, jsonrpc.ClientCloser, error) {
6363
addr, headers, err := getVenusClientInfo()
6464
if err != nil {
65-
return MiningAPI{}, nil, err
65+
return IMiningStruct{}, nil, err
6666
}
67-
node := MiningAPI{}
67+
node := IMiningStruct{}
6868
closer, err := jsonrpc.NewClient(ctx, addr, "Filecoin", &node, headers)
6969
if err != nil {
70-
return MiningAPI{}, nil, err
70+
return IMiningStruct{}, nil, err
7171
}
7272
return node, closer, nil
7373
}

app/node/builder.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import (
3030
"github.com/filecoin-project/venus/pkg/repo"
3131
"github.com/filecoin-project/venus/pkg/specactors/policy"
3232
"github.com/filecoin-project/venus/pkg/statemanger"
33-
"github.com/filecoin-project/venus/pkg/util"
3433
"github.com/filecoin-project/venus/pkg/util/ffiwrapper"
3534
"github.com/ipfs/go-cid"
3635
"github.com/libp2p/go-libp2p"
@@ -289,11 +288,12 @@ func (b *Builder) build(ctx context.Context) (*Node, error) {
289288

290289
stmgr := statemanger.NewStateMangerAPI(nd.chain.ChainReader, nd.syncer.Consensus)
291290
mgrps := &paychmgr.ManagerParams{
292-
MPoolAPI: nd.mpool.API(),
293-
ChainAPI: nd.chain.API(),
294-
Protocol: nd.syncer.Consensus,
295-
SM: stmgr,
296-
DS: b.repo.PaychDatastore(),
291+
MPoolAPI: nd.mpool.API(),
292+
ChainAPI: nd.chain.API(),
293+
Protocol: nd.syncer.Consensus,
294+
SM: stmgr,
295+
DS: b.repo.PaychDatastore(),
296+
WalletAPI: nd.wallet.API(),
297297
}
298298
nd.paychan = paych.NewPaychSubmodule(ctx, mgrps)
299299
nd.market = market.NewMarketModule(nd.chain.API(), stmgr)
@@ -315,7 +315,7 @@ func (b *Builder) build(ctx context.Context) (*Node, error) {
315315
nd.jwtCli = client
316316
}
317317

318-
apiBuilder := util.NewBuiler()
318+
apiBuilder := NewBuilder()
319319
apiBuilder.NameSpace("Filecoin")
320320
err = apiBuilder.AddServices(nd.configModule,
321321
nd.blockstore,

app/node/env.go

+17-30
Original file line numberDiff line numberDiff line change
@@ -2,44 +2,31 @@ package node
22

33
import (
44
"context"
5-
"github.com/filecoin-project/venus/app/submodule/market"
6-
"github.com/filecoin-project/venus/app/submodule/multisig"
7-
"github.com/filecoin-project/venus/app/submodule/paych"
8-
5+
"github.com/filecoin-project/venus/app/submodule/apiface"
96
cmds "github.com/ipfs/go-ipfs-cmds"
107

11-
"github.com/filecoin-project/venus/app/submodule/blockservice"
12-
"github.com/filecoin-project/venus/app/submodule/blockstore"
13-
"github.com/filecoin-project/venus/app/submodule/chain"
14-
"github.com/filecoin-project/venus/app/submodule/config"
15-
"github.com/filecoin-project/venus/app/submodule/discovery"
16-
"github.com/filecoin-project/venus/app/submodule/mining"
17-
"github.com/filecoin-project/venus/app/submodule/mpool"
18-
"github.com/filecoin-project/venus/app/submodule/network"
198
"github.com/filecoin-project/venus/app/submodule/storagenetworking"
20-
"github.com/filecoin-project/venus/app/submodule/syncer"
21-
"github.com/filecoin-project/venus/app/submodule/wallet"
229
)
2310

2411
// Env is the environment for command API handlers.
2512
type Env struct {
2613
ctx context.Context
27-
InspectorAPI *Inspector
28-
BlockServiceAPI *blockservice.BlockServiceAPI
29-
BlockStoreAPI *blockstore.BlockstoreAPI
30-
ChainAPI *chain.ChainAPI
31-
ConfigAPI *config.ConfigAPI
32-
DiscoveryAPI *discovery.DiscoveryAPI
33-
NetworkAPI *network.NetworkAPI
34-
StorageNetworkingAPI *storagenetworking.StorageNetworkingAPI
35-
SyncerAPI *syncer.SyncerAPI
36-
WalletAPI *wallet.WalletAPI
37-
MingingAPI *mining.MiningAPI
38-
MessagePoolAPI *mpool.MessagePoolAPI
39-
40-
MultiSigAPI multisig.IMultiSig
41-
MarketAPI market.IMarket
42-
PaychAPI paych.IPaychan
14+
InspectorAPI IInspector
15+
BlockServiceAPI apiface.IBlockService
16+
BlockStoreAPI apiface.IBlockStore
17+
ChainAPI apiface.IChain
18+
ConfigAPI apiface.IConfig
19+
DiscoveryAPI apiface.IDiscovery
20+
NetworkAPI apiface.INetwork
21+
StorageNetworkingAPI storagenetworking.IStorageNetworking
22+
SyncerAPI apiface.ISyncer
23+
WalletAPI apiface.IWallet
24+
MingingAPI apiface.IMining
25+
MessagePoolAPI apiface.IMessagePool
26+
27+
MultiSigAPI apiface.IMultiSig
28+
MarketAPI apiface.IMarket
29+
PaychAPI apiface.IPaychan
4330
}
4431

4532
var _ cmds.Environment = (*Env)(nil)

app/node/inspector_api.go

+20-9
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,26 @@ import (
1010
"runtime"
1111
)
1212

13+
type IInspector interface {
14+
Runtime() *RuntimeInfo
15+
Memory() (*MemoryInfo, error)
16+
Config() *config.Config
17+
Disk() (*DiskInfo, error)
18+
FilecoinVersion() string
19+
Environment() *EnvironmentInfo
20+
}
21+
22+
var _ IInspector = &inspector{}
23+
1324
// NewInspectorAPI returns a `Inspector` used to inspect the venus node.
14-
func NewInspectorAPI(r repo.Repo) *Inspector {
15-
return &Inspector{
25+
func NewInspectorAPI(r repo.Repo) IInspector {
26+
return &inspector{
1627
repo: r,
1728
}
1829
}
1930

2031
// Inspector contains information used to inspect the venus node.
21-
type Inspector struct {
32+
type inspector struct {
2233
repo repo.Repo
2334
}
2435

@@ -65,7 +76,7 @@ type MemoryInfo struct {
6576
}
6677

6778
// Runtime returns infrormation about the golang runtime.
68-
func (g *Inspector) Runtime() *RuntimeInfo {
79+
func (g *inspector) Runtime() *RuntimeInfo {
6980
return &RuntimeInfo{
7081
OS: runtime.GOOS,
7182
Arch: runtime.GOARCH,
@@ -79,7 +90,7 @@ func (g *Inspector) Runtime() *RuntimeInfo {
7990
}
8091

8192
// Environment returns information about the environment filecoin is running in.
82-
func (g *Inspector) Environment() *EnvironmentInfo {
93+
func (g *inspector) Environment() *EnvironmentInfo {
8394
return &EnvironmentInfo{
8495
FilAPI: os.Getenv("FIL_API"),
8596
FilPath: os.Getenv("FIL_PATH"),
@@ -88,7 +99,7 @@ func (g *Inspector) Environment() *EnvironmentInfo {
8899
}
89100

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

119130
// Memory return information about system meory usage.
120-
func (g *Inspector) Memory() (*MemoryInfo, error) {
131+
func (g *inspector) Memory() (*MemoryInfo, error) {
121132
meminfo, err := sysi.MemoryInfo()
122133
if err != nil {
123134
return nil, err
@@ -129,11 +140,11 @@ func (g *Inspector) Memory() (*MemoryInfo, error) {
129140
}
130141

131142
// configModule return the current config values of the filecoin node.
132-
func (g *Inspector) Config() *config.Config {
143+
func (g *inspector) Config() *config.Config {
133144
return g.repo.Config()
134145
}
135146

136147
// FilecoinVersion returns the version of venus.
137-
func (g *Inspector) FilecoinVersion() string {
148+
func (g *inspector) FilecoinVersion() string {
138149
return fmt.Sprintf("%s %s", flags.GitTag, flags.GitCommit)
139150
}

app/node/node.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,6 @@ func (node *Node) Stop(ctx context.Context) {
217217
if err := node.repo.Close(); err != nil {
218218
fmt.Printf("error closing repo: %s\n", err)
219219
}
220-
221-
fmt.Println("stopping filecoin :(")
222220
}
223221

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

298297
handler.Handle(APIPrefix+"/", cmdhttp.NewHandler(servenv, rootCmdDaemon, cfg))
299298
return nil

pkg/util/apibuilder.go app/node/rpc.go

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
package util
1+
package node
22

33
import (
44
"github.com/filecoin-project/go-jsonrpc"
5-
xerrors "github.com/pkg/errors"
5+
"github.com/filecoin-project/venus/app/client"
6+
"github.com/filecoin-project/venus/app/client/funcrule"
7+
"golang.org/x/xerrors"
68
"reflect"
79
)
810

@@ -14,7 +16,7 @@ type RPCBuilder struct {
1416
apiStruct []interface{}
1517
}
1618

17-
func NewBuiler() *RPCBuilder {
19+
func NewBuilder() *RPCBuilder {
1820
return &RPCBuilder{}
1921
}
2022

@@ -55,17 +57,17 @@ func (builder *RPCBuilder) AddService(service RPCService) error {
5557
builder.apiStruct = append(builder.apiStruct, apiImpl.Interface())
5658
}
5759
}
58-
5960
return nil
6061
}
6162

6263
func (builder *RPCBuilder) Build() *jsonrpc.RPCServer {
63-
server := jsonrpc.NewServer()
64+
server := jsonrpc.NewServer(jsonrpc.WithProxyBind(jsonrpc.PBField))
65+
var fullNode client.FullNodeStruct
66+
for _, apiStruct := range builder.apiStruct {
67+
funcrule.PermissionProxy(apiStruct, &fullNode)
68+
}
6469
for _, nameSpace := range builder.namespace {
65-
for _, apiStruct := range builder.apiStruct {
66-
//fmt.Println("JSON RPC register:", nameSpace)
67-
server.Register(nameSpace, apiStruct)
68-
}
70+
server.Register(nameSpace, &fullNode)
6971
}
7072
return server
7173
}

0 commit comments

Comments
 (0)