2020-09-21 09:51:15 +00:00
|
|
|
package acl
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
2020-09-21 13:33:49 +00:00
|
|
|
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/v2/container"
|
2020-09-21 09:51:15 +00:00
|
|
|
"github.com/nspcc-dev/neofs-api-go/v2/object"
|
2020-09-21 13:33:49 +00:00
|
|
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
|
|
|
"github.com/pkg/errors"
|
2020-09-21 09:51:15 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
// ContainerGetter accesses NeoFS container storage.
|
2020-09-21 13:33:49 +00:00
|
|
|
ContainerGetter interface {
|
|
|
|
Get(*refs.ContainerID) (*container.Container, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
Classifier interface {
|
|
|
|
Classify(RequestV2, *refs.ContainerID) acl.Role
|
|
|
|
}
|
2020-09-21 09:51:15 +00:00
|
|
|
|
|
|
|
// BasicChecker checks basic ACL rules.
|
|
|
|
BasicChecker struct {
|
2020-09-21 13:33:49 +00:00
|
|
|
sender SenderClassifier
|
|
|
|
next object.Service
|
2020-09-21 09:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
putStreamBasicChecker struct {
|
2020-09-21 13:33:49 +00:00
|
|
|
sender SenderClassifier
|
|
|
|
next object.PutObjectStreamer
|
2020-09-21 09:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
getStreamBasicChecker struct {
|
2020-09-21 13:33:49 +00:00
|
|
|
sender SenderClassifier
|
|
|
|
next object.GetObjectStreamer
|
2020-09-21 09:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
searchStreamBasicChecker struct {
|
2020-09-21 13:33:49 +00:00
|
|
|
sender SenderClassifier
|
|
|
|
next object.SearchObjectStreamer
|
2020-09-21 09:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
getRangeStreamBasicChecker struct {
|
2020-09-21 13:33:49 +00:00
|
|
|
sender SenderClassifier
|
|
|
|
next object.GetRangeObjectStreamer
|
2020-09-21 09:51:15 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2020-09-21 13:33:49 +00:00
|
|
|
var (
|
|
|
|
ErrMalformedRequest = errors.New("malformed request")
|
|
|
|
ErrUnknownRole = errors.New("can't classify request sender")
|
|
|
|
)
|
|
|
|
|
2020-09-21 09:51:15 +00:00
|
|
|
// NewBasicChecker is a constructor for basic ACL checker of object requests.
|
2020-09-21 13:33:49 +00:00
|
|
|
func NewBasicChecker(c SenderClassifier, next object.Service) BasicChecker {
|
2020-09-21 09:51:15 +00:00
|
|
|
return BasicChecker{
|
2020-09-21 13:33:49 +00:00
|
|
|
sender: c,
|
|
|
|
next: next,
|
2020-09-21 09:51:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b BasicChecker) Get(
|
|
|
|
ctx context.Context,
|
|
|
|
request *object.GetRequest) (object.GetObjectStreamer, error) {
|
|
|
|
|
2020-09-21 13:33:49 +00:00
|
|
|
// get container address and do not panic at malformed request
|
|
|
|
var addr *refs.Address
|
|
|
|
if body := request.GetBody(); body == nil {
|
|
|
|
return nil, ErrMalformedRequest
|
|
|
|
} else {
|
|
|
|
addr = body.GetAddress()
|
|
|
|
}
|
|
|
|
|
|
|
|
role := b.sender.Classify(request, addr.GetContainerID())
|
|
|
|
if role == acl.RoleUnknown {
|
|
|
|
return nil, ErrUnknownRole
|
|
|
|
}
|
|
|
|
|
2020-09-21 09:51:15 +00:00
|
|
|
stream, err := b.next.Get(ctx, request)
|
|
|
|
return getStreamBasicChecker{
|
2020-09-21 13:33:49 +00:00
|
|
|
sender: b.sender,
|
|
|
|
next: stream,
|
2020-09-21 09:51:15 +00:00
|
|
|
}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b BasicChecker) Put(ctx context.Context) (object.PutObjectStreamer, error) {
|
|
|
|
streamer, err := b.next.Put(ctx)
|
|
|
|
|
|
|
|
return putStreamBasicChecker{
|
2020-09-21 13:33:49 +00:00
|
|
|
sender: b.sender,
|
|
|
|
next: streamer,
|
2020-09-21 09:51:15 +00:00
|
|
|
}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b BasicChecker) Head(
|
|
|
|
ctx context.Context,
|
|
|
|
request *object.HeadRequest) (*object.HeadResponse, error) {
|
|
|
|
|
|
|
|
return b.next.Head(ctx, request)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b BasicChecker) Search(
|
|
|
|
ctx context.Context,
|
|
|
|
request *object.SearchRequest) (object.SearchObjectStreamer, error) {
|
|
|
|
|
|
|
|
stream, err := b.next.Search(ctx, request)
|
|
|
|
return searchStreamBasicChecker{
|
2020-09-21 13:33:49 +00:00
|
|
|
sender: b.sender,
|
|
|
|
next: stream,
|
2020-09-21 09:51:15 +00:00
|
|
|
}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b BasicChecker) Delete(
|
|
|
|
ctx context.Context,
|
|
|
|
request *object.DeleteRequest) (*object.DeleteResponse, error) {
|
|
|
|
|
|
|
|
return b.next.Delete(ctx, request)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b BasicChecker) GetRange(
|
|
|
|
ctx context.Context,
|
|
|
|
request *object.GetRangeRequest) (object.GetRangeObjectStreamer, error) {
|
|
|
|
|
|
|
|
stream, err := b.next.GetRange(ctx, request)
|
|
|
|
return getRangeStreamBasicChecker{
|
2020-09-21 13:33:49 +00:00
|
|
|
sender: b.sender,
|
|
|
|
next: stream,
|
2020-09-21 09:51:15 +00:00
|
|
|
}, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b BasicChecker) GetRangeHash(
|
|
|
|
ctx context.Context,
|
|
|
|
request *object.GetRangeHashRequest) (*object.GetRangeHashResponse, error) {
|
|
|
|
|
|
|
|
return b.next.GetRangeHash(ctx, request)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p putStreamBasicChecker) Send(request *object.PutRequest) error {
|
|
|
|
return p.next.Send(request)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p putStreamBasicChecker) CloseAndRecv() (*object.PutResponse, error) {
|
|
|
|
return p.next.CloseAndRecv()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g getStreamBasicChecker) Recv() (*object.GetResponse, error) {
|
|
|
|
return g.next.Recv()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s searchStreamBasicChecker) Recv() (*object.SearchResponse, error) {
|
|
|
|
return s.next.Recv()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g getRangeStreamBasicChecker) Recv() (*object.GetRangeResponse, error) {
|
|
|
|
return g.next.Recv()
|
|
|
|
}
|