[#414] ir: Serve ControlService
Serve `ControlService` instance on configured endpoint (do not serve if not specified). Read allowed keys from config. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
4001ba2967
commit
455fd952dd
5 changed files with 73 additions and 10 deletions
|
@ -117,4 +117,7 @@ func defaultConfiguration(cfg *viper.Viper) {
|
||||||
// extra fee values for working mode without notary contract
|
// extra fee values for working mode without notary contract
|
||||||
cfg.SetDefault("fee.main_chain", 5000_0000) // 0.5 Fixed8
|
cfg.SetDefault("fee.main_chain", 5000_0000) // 0.5 Fixed8
|
||||||
cfg.SetDefault("fee.side_chain", 2_0000_0000) // 2.0 Fixed8
|
cfg.SetDefault("fee.side_chain", 2_0000_0000) // 2.0 Fixed8
|
||||||
|
|
||||||
|
cfg.SetDefault("control.authorized_keys", []string{})
|
||||||
|
cfg.SetDefault("control.grpc.endpoint", "")
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,11 @@ package innerring
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"net"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
@ -32,6 +34,8 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/morph/subscriber"
|
"github.com/nspcc-dev/neofs-node/pkg/morph/subscriber"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/morph/timer"
|
"github.com/nspcc-dev/neofs-node/pkg/morph/timer"
|
||||||
audittask "github.com/nspcc-dev/neofs-node/pkg/services/audit/taskmanager"
|
audittask "github.com/nspcc-dev/neofs-node/pkg/services/audit/taskmanager"
|
||||||
|
control "github.com/nspcc-dev/neofs-node/pkg/services/control/ir"
|
||||||
|
controlsrv "github.com/nspcc-dev/neofs-node/pkg/services/control/ir/server"
|
||||||
util2 "github.com/nspcc-dev/neofs-node/pkg/util"
|
util2 "github.com/nspcc-dev/neofs-node/pkg/util"
|
||||||
utilConfig "github.com/nspcc-dev/neofs-node/pkg/util/config"
|
utilConfig "github.com/nspcc-dev/neofs-node/pkg/util/config"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/util/precision"
|
"github.com/nspcc-dev/neofs-node/pkg/util/precision"
|
||||||
|
@ -39,6 +43,7 @@ import (
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"go.uber.org/atomic"
|
"go.uber.org/atomic"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -91,6 +96,13 @@ type (
|
||||||
//
|
//
|
||||||
// Errors are logged.
|
// Errors are logged.
|
||||||
closers []func() error
|
closers []func() error
|
||||||
|
|
||||||
|
// Set of component runners which
|
||||||
|
// should report start errors
|
||||||
|
// to the application.
|
||||||
|
//
|
||||||
|
// TODO: unify with workers.
|
||||||
|
runners []func(chan<- error)
|
||||||
}
|
}
|
||||||
|
|
||||||
contracts struct {
|
contracts struct {
|
||||||
|
@ -152,7 +164,7 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err := s.initConfigFromBlockchain()
|
err = s.initConfigFromBlockchain()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -210,6 +222,10 @@ func (s *Server) Start(ctx context.Context, intError chan<- error) (err error) {
|
||||||
s.tickTimers()
|
s.tickTimers()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
for _, runner := range s.runners {
|
||||||
|
runner(intError)
|
||||||
|
}
|
||||||
|
|
||||||
go s.morphListener.ListenWithError(ctx, morphErr) // listen for neo:morph events
|
go s.morphListener.ListenWithError(ctx, morphErr) // listen for neo:morph events
|
||||||
go s.mainnetListener.ListenWithError(ctx, mainnnetErr) // listen for neo:mainnet events
|
go s.mainnetListener.ListenWithError(ctx, mainnnetErr) // listen for neo:mainnet events
|
||||||
|
|
||||||
|
@ -285,6 +301,8 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error
|
||||||
|
|
||||||
server.key = acc.PrivateKey()
|
server.key = acc.PrivateKey()
|
||||||
|
|
||||||
|
fmt.Println(hex.EncodeToString(server.key.PublicKey().Bytes()))
|
||||||
|
|
||||||
// get all script hashes of contracts
|
// get all script hashes of contracts
|
||||||
server.contracts, err = parseContracts(cfg)
|
server.contracts, err = parseContracts(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -728,6 +746,52 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error
|
||||||
server.addBlockTimer(sideNotaryTimer)
|
server.addBlockTimer(sideNotaryTimer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
controlSvcEndpoint := cfg.GetString("control.grpc.endpoint")
|
||||||
|
if controlSvcEndpoint != "" {
|
||||||
|
authKeysStr := cfg.GetStringSlice("control.authorized_keys")
|
||||||
|
authKeys := make([][]byte, 0, len(authKeysStr))
|
||||||
|
|
||||||
|
for i := range authKeysStr {
|
||||||
|
key, err := hex.DecodeString(authKeysStr[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not parse Control authorized key %s: %w",
|
||||||
|
authKeysStr[i],
|
||||||
|
err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
authKeys = append(authKeys, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
var p controlsrv.Prm
|
||||||
|
|
||||||
|
p.SetPrivateKey(*server.key)
|
||||||
|
p.SetHealthChecker(server)
|
||||||
|
|
||||||
|
controlSvc := controlsrv.New(p,
|
||||||
|
controlsrv.WithAllowedKeys(authKeys),
|
||||||
|
)
|
||||||
|
|
||||||
|
grpcControlSrv := grpc.NewServer()
|
||||||
|
control.RegisterControlServiceServer(grpcControlSrv, controlSvc)
|
||||||
|
|
||||||
|
server.runners = append(server.runners, func(ch chan<- error) {
|
||||||
|
lis, err := net.Listen("tcp", controlSvcEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
ch <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
ch <- grpcControlSrv.Serve(lis)
|
||||||
|
}()
|
||||||
|
})
|
||||||
|
|
||||||
|
server.registerNoErrCloser(grpcControlSrv.GracefulStop)
|
||||||
|
} else {
|
||||||
|
log.Info("no Control server endpoint specified, service is disabled")
|
||||||
|
}
|
||||||
|
|
||||||
return server, nil
|
return server, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ func (s *Server) HealthCheck(_ context.Context, req *control.HealthCheckRequest)
|
||||||
body.SetHealthStatus(s.prm.healthChecker.HealthStatus())
|
body.SetHealthStatus(s.prm.healthChecker.HealthStatus())
|
||||||
|
|
||||||
// sign the response
|
// sign the response
|
||||||
if err := SignMessage(s.prm.key, resp); err != nil {
|
if err := SignMessage(&s.prm.key.PrivateKey, resp); err != nil {
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, status.Error(codes.Internal, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
package control
|
package control
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Prm groups required parameters of
|
// Prm groups required parameters of
|
||||||
// Server's constructor.
|
// Server's constructor.
|
||||||
type Prm struct {
|
type Prm struct {
|
||||||
key *ecdsa.PrivateKey
|
key keys.PrivateKey
|
||||||
|
|
||||||
healthChecker HealthChecker
|
healthChecker HealthChecker
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPrivateKey sets private key to sign responses.
|
// SetPrivateKey sets private key to sign responses.
|
||||||
func (x *Prm) SetPrivateKey(key *ecdsa.PrivateKey) {
|
func (x *Prm) SetPrivateKey(key keys.PrivateKey) {
|
||||||
x.key = key
|
x.key = key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,6 @@ package control
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Server is an entity that serves
|
// Server is an entity that serves
|
||||||
|
@ -34,8 +32,6 @@ func panicOnPrmValue(n string, v interface{}) {
|
||||||
func New(prm Prm, opts ...Option) *Server {
|
func New(prm Prm, opts ...Option) *Server {
|
||||||
// verify required parameters
|
// verify required parameters
|
||||||
switch {
|
switch {
|
||||||
case prm.key == nil:
|
|
||||||
panicOnPrmValue("key", prm.key)
|
|
||||||
case prm.healthChecker == nil:
|
case prm.healthChecker == nil:
|
||||||
panicOnPrmValue("health checker", prm.healthChecker)
|
panicOnPrmValue("health checker", prm.healthChecker)
|
||||||
}
|
}
|
||||||
|
@ -50,6 +46,6 @@ func New(prm Prm, opts ...Option) *Server {
|
||||||
return &Server{
|
return &Server{
|
||||||
prm: prm,
|
prm: prm,
|
||||||
|
|
||||||
allowedKeys: append(o.allowedKeys, crypto.MarshalPublicKey(&prm.key.PublicKey)),
|
allowedKeys: append(o.allowedKeys, prm.key.PublicKey().Bytes()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue