forked from TrueCloudLab/frostfs-api-go
initial
This commit is contained in:
commit
1cf33e5ffd
87 changed files with 29835 additions and 0 deletions
7
service/epoch.go
Normal file
7
service/epoch.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
package service
|
||||
|
||||
// EpochRequest interface gives possibility to get or set epoch in RPC Requests.
|
||||
type EpochRequest interface {
|
||||
GetEpoch() uint64
|
||||
SetEpoch(v uint64)
|
||||
}
|
24
service/role.go
Normal file
24
service/role.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package service
|
||||
|
||||
// NodeRole to identify in Bootstrap service.
|
||||
type NodeRole int32
|
||||
|
||||
const (
|
||||
_ NodeRole = iota
|
||||
// InnerRingNode that work like IR node.
|
||||
InnerRingNode
|
||||
// StorageNode that work like a storage node.
|
||||
StorageNode
|
||||
)
|
||||
|
||||
// String is method, that represent NodeRole as string.
|
||||
func (nt NodeRole) String() string {
|
||||
switch nt {
|
||||
case InnerRingNode:
|
||||
return "InnerRingNode"
|
||||
case StorageNode:
|
||||
return "StorageNode"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
22
service/role_test.go
Normal file
22
service/role_test.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNodeRole_String(t *testing.T) {
|
||||
tests := []struct {
|
||||
nt NodeRole
|
||||
want string
|
||||
}{
|
||||
{want: "Unknown"},
|
||||
{nt: StorageNode, want: "StorageNode"},
|
||||
{nt: InnerRingNode, want: "InnerRingNode"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.want, func(t *testing.T) {
|
||||
require.Equal(t, tt.want, tt.nt.String())
|
||||
})
|
||||
}
|
||||
}
|
47
service/sign.go
Normal file
47
service/sign.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
|
||||
crypto "github.com/nspcc-dev/neofs-crypto"
|
||||
"github.com/nspcc-dev/neofs-proto/internal"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ErrWrongSignature should be raised when wrong signature is passed into VerifyRequest.
|
||||
const ErrWrongSignature = internal.Error("wrong signature")
|
||||
|
||||
// SignedRequest interface allows sign and verify requests.
|
||||
type SignedRequest interface {
|
||||
PrepareData() ([]byte, error)
|
||||
GetSignature() []byte
|
||||
SetSignature([]byte)
|
||||
}
|
||||
|
||||
// SignRequest with passed private key.
|
||||
func SignRequest(r SignedRequest, key *ecdsa.PrivateKey) error {
|
||||
var signature []byte
|
||||
if data, err := r.PrepareData(); err != nil {
|
||||
return err
|
||||
} else if signature, err = crypto.Sign(key, data); err != nil {
|
||||
return errors.Wrap(err, "could not sign data")
|
||||
}
|
||||
|
||||
r.SetSignature(signature)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifyRequest by passed public keys.
|
||||
func VerifyRequest(r SignedRequest, keys ...*ecdsa.PublicKey) bool {
|
||||
data, err := r.PrepareData()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
for i := range keys {
|
||||
if err := crypto.Verify(keys[i], data, r.GetSignature()); err == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
45
service/ttl.go
Normal file
45
service/ttl.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-proto/internal"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// TTLRequest to verify and update ttl requests.
|
||||
type TTLRequest interface {
|
||||
GetTTL() uint32
|
||||
SetTTL(uint32)
|
||||
}
|
||||
|
||||
const (
|
||||
// ZeroTTL is empty ttl, should produce ErrZeroTTL.
|
||||
ZeroTTL = iota
|
||||
|
||||
// NonForwardingTTL is a ttl that allows direct connections only.
|
||||
NonForwardingTTL
|
||||
|
||||
// SingleForwardingTTL is a ttl that allows connections through another node.
|
||||
SingleForwardingTTL
|
||||
|
||||
// ErrZeroTTL is raised when zero ttl is passed.
|
||||
ErrZeroTTL = internal.Error("zero ttl")
|
||||
|
||||
// ErrIncorrectTTL is raised when NonForwardingTTL is passed and NodeRole != InnerRingNode.
|
||||
ErrIncorrectTTL = internal.Error("incorrect ttl")
|
||||
)
|
||||
|
||||
// CheckTTLRequest validates and update ttl requests.
|
||||
func CheckTTLRequest(req TTLRequest, role NodeRole) error {
|
||||
var ttl = req.GetTTL()
|
||||
|
||||
if ttl == ZeroTTL {
|
||||
return status.New(codes.InvalidArgument, ErrZeroTTL.Error()).Err()
|
||||
} else if ttl == NonForwardingTTL && role != InnerRingNode {
|
||||
return status.New(codes.InvalidArgument, ErrIncorrectTTL.Error()).Err()
|
||||
}
|
||||
|
||||
req.SetTTL(ttl - 1)
|
||||
|
||||
return nil
|
||||
}
|
72
service/ttl_test.go
Normal file
72
service/ttl_test.go
Normal file
|
@ -0,0 +1,72 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type mockedRequest struct {
|
||||
msg string
|
||||
ttl uint32
|
||||
name string
|
||||
role NodeRole
|
||||
code codes.Code
|
||||
}
|
||||
|
||||
func (m *mockedRequest) SetTTL(v uint32) { m.ttl = v }
|
||||
func (m mockedRequest) GetTTL() uint32 { return m.ttl }
|
||||
|
||||
func TestCheckTTLRequest(t *testing.T) {
|
||||
tests := []mockedRequest{
|
||||
{
|
||||
ttl: NonForwardingTTL,
|
||||
role: InnerRingNode,
|
||||
name: "direct to ir node",
|
||||
},
|
||||
{
|
||||
ttl: NonForwardingTTL,
|
||||
role: StorageNode,
|
||||
code: codes.InvalidArgument,
|
||||
msg: ErrIncorrectTTL.Error(),
|
||||
name: "direct to storage node",
|
||||
},
|
||||
{
|
||||
ttl: ZeroTTL,
|
||||
role: StorageNode,
|
||||
msg: ErrZeroTTL.Error(),
|
||||
code: codes.InvalidArgument,
|
||||
name: "zero ttl",
|
||||
},
|
||||
{
|
||||
ttl: SingleForwardingTTL,
|
||||
role: InnerRingNode,
|
||||
name: "default to ir node",
|
||||
},
|
||||
{
|
||||
ttl: SingleForwardingTTL,
|
||||
role: StorageNode,
|
||||
name: "default to storage node",
|
||||
},
|
||||
}
|
||||
|
||||
for i := range tests {
|
||||
tt := tests[i]
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
before := tt.ttl
|
||||
err := CheckTTLRequest(&tt, tt.role)
|
||||
if tt.msg != "" {
|
||||
require.Errorf(t, err, tt.msg)
|
||||
|
||||
state, ok := status.FromError(err)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, state.Code(), tt.code)
|
||||
require.Equal(t, state.Message(), tt.msg)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.NotEqualf(t, before, tt.ttl, "ttl should be changed: %d vs %d", before, tt.ttl)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue