console/userinfo: stub userinfo endpoint
This change stubs userinfo endpoint from storj/common/pb/userinfo.proto. It also adds config for allowed peers, and a method for verifying peers. Issue: https://github.com/storj/storj/issues/5358 Change-Id: I057a0e873a9e9b3b9ad0bba69305f0d708bd9b9e
This commit is contained in:
parent
dcb16d83dd
commit
e598c2b3b1
@ -39,6 +39,7 @@ import (
|
|||||||
"storj.io/storj/satellite/compensation"
|
"storj.io/storj/satellite/compensation"
|
||||||
"storj.io/storj/satellite/console"
|
"storj.io/storj/satellite/console"
|
||||||
"storj.io/storj/satellite/console/consoleweb"
|
"storj.io/storj/satellite/console/consoleweb"
|
||||||
|
"storj.io/storj/satellite/console/userinfo"
|
||||||
"storj.io/storj/satellite/contact"
|
"storj.io/storj/satellite/contact"
|
||||||
"storj.io/storj/satellite/gc/bloomfilter"
|
"storj.io/storj/satellite/gc/bloomfilter"
|
||||||
"storj.io/storj/satellite/gc/sender"
|
"storj.io/storj/satellite/gc/sender"
|
||||||
@ -113,6 +114,10 @@ type Satellite struct {
|
|||||||
SegmentLoop *segmentloop.Service
|
SegmentLoop *segmentloop.Service
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Userinfo struct {
|
||||||
|
Endpoint *userinfo.Endpoint
|
||||||
|
}
|
||||||
|
|
||||||
Metabase struct {
|
Metabase struct {
|
||||||
DB *metabase.DB
|
DB *metabase.DB
|
||||||
SegmentLoop *segmentloop.Service
|
SegmentLoop *segmentloop.Service
|
||||||
@ -616,6 +621,8 @@ func createNewSystem(name string, log *zap.Logger, config satellite.Config, peer
|
|||||||
system.Metainfo.Endpoint = api.Metainfo.Endpoint
|
system.Metainfo.Endpoint = api.Metainfo.Endpoint
|
||||||
// system.Metainfo.SegmentLoop = peer.Metainfo.SegmentLoop
|
// system.Metainfo.SegmentLoop = peer.Metainfo.SegmentLoop
|
||||||
|
|
||||||
|
system.Userinfo.Endpoint = api.Userinfo.Endpoint
|
||||||
|
|
||||||
system.Metabase.DB = api.Metainfo.Metabase
|
system.Metabase.DB = api.Metainfo.Metabase
|
||||||
system.Metabase.SegmentLoop = peer.Metainfo.SegmentLoop
|
system.Metabase.SegmentLoop = peer.Metainfo.SegmentLoop
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ import (
|
|||||||
"storj.io/storj/satellite/console/consoleauth"
|
"storj.io/storj/satellite/console/consoleauth"
|
||||||
"storj.io/storj/satellite/console/consoleweb"
|
"storj.io/storj/satellite/console/consoleweb"
|
||||||
"storj.io/storj/satellite/console/restkeys"
|
"storj.io/storj/satellite/console/restkeys"
|
||||||
|
"storj.io/storj/satellite/console/userinfo"
|
||||||
"storj.io/storj/satellite/contact"
|
"storj.io/storj/satellite/contact"
|
||||||
"storj.io/storj/satellite/gracefulexit"
|
"storj.io/storj/satellite/gracefulexit"
|
||||||
"storj.io/storj/satellite/inspector"
|
"storj.io/storj/satellite/inspector"
|
||||||
@ -107,6 +108,10 @@ type API struct {
|
|||||||
Endpoint *metainfo.Endpoint
|
Endpoint *metainfo.Endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Userinfo struct {
|
||||||
|
Endpoint *userinfo.Endpoint
|
||||||
|
}
|
||||||
|
|
||||||
Inspector struct {
|
Inspector struct {
|
||||||
Endpoint *inspector.Endpoint
|
Endpoint *inspector.Endpoint
|
||||||
}
|
}
|
||||||
|
99
satellite/console/userinfo/endpoint.go
Normal file
99
satellite/console/userinfo/endpoint.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// Copyright (C) 2022 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
package userinfo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/spacemonkeygo/monkit/v3"
|
||||||
|
"github.com/zeebo/errs"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
"storj.io/common/identity"
|
||||||
|
"storj.io/common/pb"
|
||||||
|
"storj.io/common/rpc/rpcpeer"
|
||||||
|
"storj.io/common/rpc/rpcstatus"
|
||||||
|
"storj.io/common/storj"
|
||||||
|
"storj.io/storj/satellite/console"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
mon = monkit.Package()
|
||||||
|
// Error is an error class for userinfo endpoint errors.
|
||||||
|
Error = errs.Class("userinfo_endpoint")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config holds Endpoint's configuration.
|
||||||
|
type Config struct {
|
||||||
|
AllowedPeers storj.NodeURLs `help:"A comma delimited list of peers (IDs/addresses) allowed to use this endpoint."`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Endpoint userinfo endpoint.
|
||||||
|
type Endpoint struct {
|
||||||
|
pb.DRPCUserInfoUnimplementedServer
|
||||||
|
|
||||||
|
log *zap.Logger
|
||||||
|
users console.Users
|
||||||
|
apiKeys console.APIKeys
|
||||||
|
projects console.Projects
|
||||||
|
config Config
|
||||||
|
allowedPeers map[storj.NodeID]storj.NodeURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEndpoint creates a new userinfo endpoint instance.
|
||||||
|
func NewEndpoint(log *zap.Logger, users console.Users, apiKeys console.APIKeys, projects console.Projects, config Config) (*Endpoint, error) {
|
||||||
|
if len(config.AllowedPeers) == 0 {
|
||||||
|
return nil, Error.New("allowed peer list parameter '--allowed-peer-list' is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
// put peers into a map for faster retrieval by NodeID.
|
||||||
|
allowedPeers := make(map[storj.NodeID]storj.NodeURL)
|
||||||
|
for _, peer := range config.AllowedPeers {
|
||||||
|
allowedPeers[peer.ID] = peer
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Endpoint{
|
||||||
|
log: log,
|
||||||
|
users: users,
|
||||||
|
apiKeys: apiKeys,
|
||||||
|
projects: projects,
|
||||||
|
config: config,
|
||||||
|
allowedPeers: allowedPeers,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes resources.
|
||||||
|
func (e *Endpoint) Close() error { return nil }
|
||||||
|
|
||||||
|
// Get returns relevant info about the current user.
|
||||||
|
func (e *Endpoint) Get(ctx context.Context, _ *pb.GetUserInfoRequest) (response *pb.GetUserInfoResponse, err error) {
|
||||||
|
defer mon.Task()(&ctx)(&err)
|
||||||
|
|
||||||
|
peer, err := rpcpeer.FromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, rpcstatus.Error(rpcstatus.Internal, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
peerID, err := identity.PeerIdentityFromPeer(peer)
|
||||||
|
if err != nil {
|
||||||
|
return nil, rpcstatus.Error(rpcstatus.Unauthenticated, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = e.verifyPeer(peerID.ID); err != nil {
|
||||||
|
return nil, rpcstatus.Error(rpcstatus.Unauthenticated, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement get user info
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// verifyPeer verifies that a peer is allowed.
|
||||||
|
func (e *Endpoint) verifyPeer(id storj.NodeID) error {
|
||||||
|
_, ok := e.allowedPeers[id]
|
||||||
|
if !ok {
|
||||||
|
return Error.New("peer %q is untrusted", id)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
72
satellite/console/userinfo/endpoint_test.go
Normal file
72
satellite/console/userinfo/endpoint_test.go
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
// Copyright (C) 2022 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
package userinfo_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
"storj.io/common/identity/testidentity"
|
||||||
|
"storj.io/common/pb"
|
||||||
|
"storj.io/common/rpc/rpcpeer"
|
||||||
|
"storj.io/common/storj"
|
||||||
|
"storj.io/common/testcontext"
|
||||||
|
"storj.io/storj/private/testplanet"
|
||||||
|
"storj.io/storj/satellite"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEndpointGet_UnTrusted(t *testing.T) {
|
||||||
|
t.Skip("disable until UserInfo is added to API. See issue #5363")
|
||||||
|
|
||||||
|
// trusted identity
|
||||||
|
ident, err := testidentity.NewTestIdentity(context.TODO())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
testplanet.Run(t, testplanet.Config{
|
||||||
|
SatelliteCount: 1,
|
||||||
|
Reconfigure: testplanet.Reconfigure{
|
||||||
|
Satellite: func(log *zap.Logger, index int, config *satellite.Config) {
|
||||||
|
url, err := storj.ParseNodeURL(ident.ID.String() + "@")
|
||||||
|
require.NoError(t, err)
|
||||||
|
config.Userinfo.AllowedPeers = storj.NodeURLs{url}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||||
|
sat := planet.Satellites[0]
|
||||||
|
|
||||||
|
state := tls.ConnectionState{
|
||||||
|
PeerCertificates: []*x509.Certificate{ident.Leaf, ident.CA},
|
||||||
|
}
|
||||||
|
peerCtx := rpcpeer.NewContext(ctx, &rpcpeer.Peer{
|
||||||
|
Addr: sat.API.Console.Listener.Addr(),
|
||||||
|
State: state,
|
||||||
|
})
|
||||||
|
_, err = sat.Userinfo.Endpoint.Get(peerCtx, &pb.GetUserInfoRequest{})
|
||||||
|
// a trusted peer should be able to get Userinfo
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// untrusted identity
|
||||||
|
badIdent, err := testidentity.NewTestIdentity(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
state = tls.ConnectionState{
|
||||||
|
PeerCertificates: []*x509.Certificate{badIdent.Leaf, badIdent.CA},
|
||||||
|
}
|
||||||
|
peerCtx = rpcpeer.NewContext(ctx, &rpcpeer.Peer{
|
||||||
|
Addr: sat.API.Console.Listener.Addr(),
|
||||||
|
State: state,
|
||||||
|
})
|
||||||
|
_, err = sat.Userinfo.Endpoint.Get(peerCtx, &pb.GetUserInfoRequest{})
|
||||||
|
// an untrusted peer shouldn't be able to get Userinfo
|
||||||
|
require.Error(t, err)
|
||||||
|
require.EqualError(t, err, fmt.Sprintf("userinfo_endpoint: peer %q is untrusted", badIdent.ID))
|
||||||
|
})
|
||||||
|
}
|
@ -36,6 +36,7 @@ import (
|
|||||||
"storj.io/storj/satellite/console/consoleweb"
|
"storj.io/storj/satellite/console/consoleweb"
|
||||||
"storj.io/storj/satellite/console/emailreminders"
|
"storj.io/storj/satellite/console/emailreminders"
|
||||||
"storj.io/storj/satellite/console/restkeys"
|
"storj.io/storj/satellite/console/restkeys"
|
||||||
|
"storj.io/storj/satellite/console/userinfo"
|
||||||
"storj.io/storj/satellite/contact"
|
"storj.io/storj/satellite/contact"
|
||||||
"storj.io/storj/satellite/gc/bloomfilter"
|
"storj.io/storj/satellite/gc/bloomfilter"
|
||||||
"storj.io/storj/satellite/gc/sender"
|
"storj.io/storj/satellite/gc/sender"
|
||||||
@ -153,6 +154,8 @@ type Config struct {
|
|||||||
Metainfo metainfo.Config
|
Metainfo metainfo.Config
|
||||||
Orders orders.Config
|
Orders orders.Config
|
||||||
|
|
||||||
|
Userinfo userinfo.Config
|
||||||
|
|
||||||
Reputation reputation.Config
|
Reputation reputation.Config
|
||||||
|
|
||||||
Checker checker.Config
|
Checker checker.Config
|
||||||
|
3
scripts/testdata/satellite-config.yaml.lock
vendored
3
scripts/testdata/satellite-config.yaml.lock
vendored
@ -1063,6 +1063,9 @@ server.private-address: 127.0.0.1:7778
|
|||||||
# how frequent to sample traces
|
# how frequent to sample traces
|
||||||
# tracing.sample: 0
|
# tracing.sample: 0
|
||||||
|
|
||||||
|
# A comma delimited list of peers (IDs/addresses) allowed to use this endpoint.
|
||||||
|
# userinfo.allowed-peers: ""
|
||||||
|
|
||||||
# Interval to check the version
|
# Interval to check the version
|
||||||
# version.check-interval: 15m0s
|
# version.check-interval: 15m0s
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user