166 lines
4.9 KiB
Go
166 lines
4.9 KiB
Go
// Copyright (C) 2019 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package pointerdb
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
"github.com/gogo/protobuf/proto"
|
|
"github.com/golang/protobuf/ptypes"
|
|
"github.com/golang/protobuf/ptypes/timestamp"
|
|
"github.com/skyrings/skyring-common/tools/uuid"
|
|
|
|
"storj.io/storj/pkg/auth"
|
|
"storj.io/storj/pkg/certdb"
|
|
"storj.io/storj/pkg/identity"
|
|
"storj.io/storj/pkg/pb"
|
|
"storj.io/storj/pkg/storj"
|
|
)
|
|
|
|
// AllocationSigner structure
|
|
type AllocationSigner struct {
|
|
satelliteIdentity *identity.FullIdentity
|
|
bwExpiration int
|
|
certdb certdb.DB
|
|
}
|
|
|
|
// NewAllocationSigner creates new instance
|
|
func NewAllocationSigner(satelliteIdentity *identity.FullIdentity, bwExpiration int, upldb certdb.DB) *AllocationSigner {
|
|
return &AllocationSigner{
|
|
satelliteIdentity: satelliteIdentity,
|
|
bwExpiration: bwExpiration,
|
|
certdb: upldb,
|
|
}
|
|
}
|
|
|
|
// PayerBandwidthAllocation returns generated payer bandwidth allocation
|
|
func (allocation *AllocationSigner) PayerBandwidthAllocation(ctx context.Context, peerIdentity *identity.PeerIdentity, action pb.BandwidthAction) (pba *pb.OrderLimit, err error) {
|
|
if peerIdentity == nil {
|
|
return nil, Error.New("missing peer identity")
|
|
}
|
|
serialNum, err := uuid.New()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
created := time.Now().Unix()
|
|
// convert ttl from days to seconds
|
|
ttl := allocation.bwExpiration
|
|
ttl *= 86400
|
|
|
|
// store the corresponding uplink's id and public key into certDB db
|
|
err = allocation.certdb.SavePublicKey(ctx, peerIdentity.ID, peerIdentity.Leaf.PublicKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := allocation.restrictActions(peerIdentity.ID, action); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
pba = &pb.OrderLimit{
|
|
SatelliteId: allocation.satelliteIdentity.ID,
|
|
UplinkId: peerIdentity.ID,
|
|
CreatedUnixSec: created,
|
|
ExpirationUnixSec: created + int64(ttl),
|
|
Action: action,
|
|
SerialNumber: serialNum.String(),
|
|
}
|
|
err = auth.SignMessage(pba, *allocation.satelliteIdentity)
|
|
return pba, err
|
|
}
|
|
|
|
// OrderLimitParameters parameters necessary to create OrderLimit
|
|
type OrderLimitParameters struct {
|
|
UplinkIdentity *identity.PeerIdentity
|
|
StorageNodeID storj.NodeID
|
|
PieceID storj.PieceID
|
|
Action pb.PieceAction
|
|
Limit int64
|
|
PieceExpiration *timestamp.Timestamp
|
|
}
|
|
|
|
// OrderLimit returns generated order limit
|
|
func (allocation *AllocationSigner) OrderLimit(ctx context.Context, parameters OrderLimitParameters) (pba *pb.OrderLimit2, err error) {
|
|
if parameters.UplinkIdentity == nil {
|
|
return nil, Error.New("missing uplink identity")
|
|
}
|
|
serialNum, err := uuid.New()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// store the corresponding uplink's id and public key into certDB db
|
|
err = allocation.certdb.SavePublicKey(ctx, parameters.UplinkIdentity.ID, parameters.UplinkIdentity.Leaf.PublicKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err := allocation.restrictActionsOrderLimit(parameters.UplinkIdentity.ID, parameters.Action); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// convert bwExpiration from days to seconds
|
|
orderExpiration, err := ptypes.TimestampProto(time.Unix(int64(allocation.bwExpiration*86400), 0))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
pba = &pb.OrderLimit2{
|
|
SerialNumber: storj.SerialNumber(*serialNum),
|
|
SatelliteId: allocation.satelliteIdentity.ID,
|
|
UplinkId: parameters.UplinkIdentity.ID,
|
|
StorageNodeId: parameters.StorageNodeID,
|
|
PieceId: parameters.PieceID,
|
|
Action: parameters.Action,
|
|
Limit: parameters.Limit,
|
|
PieceExpiration: parameters.PieceExpiration,
|
|
OrderExpiration: orderExpiration,
|
|
}
|
|
|
|
//TODO this needs to be review if make sense
|
|
msgBytes, err := proto.Marshal(pba)
|
|
if err != nil {
|
|
return nil, auth.ErrMarshal.Wrap(err)
|
|
}
|
|
signeture, err := auth.GenerateSignature(msgBytes, allocation.satelliteIdentity)
|
|
if err != nil {
|
|
return nil, auth.ErrMarshal.Wrap(err)
|
|
}
|
|
pba.SatelliteSignature = signeture
|
|
|
|
return pba, err
|
|
}
|
|
|
|
func (allocation *AllocationSigner) restrictActions(peerID storj.NodeID, action pb.BandwidthAction) error {
|
|
switch action {
|
|
case pb.BandwidthAction_GET_REPAIR, pb.BandwidthAction_PUT_REPAIR, pb.BandwidthAction_GET_AUDIT:
|
|
if peerID != allocation.satelliteIdentity.ID {
|
|
return errors.New("action restricted to signing satellite")
|
|
}
|
|
|
|
return nil
|
|
case pb.BandwidthAction_GET, pb.BandwidthAction_PUT:
|
|
return nil
|
|
default:
|
|
return errors.New("unknown action restriction")
|
|
}
|
|
}
|
|
|
|
func (allocation *AllocationSigner) restrictActionsOrderLimit(peerID storj.NodeID, action pb.PieceAction) error {
|
|
switch action {
|
|
case pb.PieceAction_GET_REPAIR, pb.PieceAction_PUT_REPAIR, pb.PieceAction_GET_AUDIT:
|
|
if peerID != allocation.satelliteIdentity.ID {
|
|
return errors.New("action restricted to signing satellite")
|
|
}
|
|
|
|
return nil
|
|
case pb.PieceAction_GET, pb.PieceAction_PUT, pb.PieceAction_DELETE:
|
|
return nil
|
|
default:
|
|
return errors.New("unknown action restriction")
|
|
}
|
|
}
|