objsvc: Remove EACL checks #1480
13 changed files with 5 additions and 604 deletions
|
@ -21,7 +21,6 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/cache"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/cache"
|
||||||
objectTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/object/grpc"
|
objectTransportGRPC "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network/transport/object/grpc"
|
||||||
objectService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object"
|
objectService "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl"
|
|
||||||
v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2"
|
v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2"
|
||||||
objectAPE "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/ape"
|
objectAPE "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/ape"
|
||||||
objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer"
|
objectwriter "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/common/writer"
|
||||||
|
@ -39,7 +38,6 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/policer"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/policer"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/replicator"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
|
||||||
netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
|
@ -458,17 +456,10 @@ func createSplitService(c *cfg, sPutV2 *putsvcV2.Service, sGetV2 *getsvcV2.Servi
|
||||||
}
|
}
|
||||||
|
|
||||||
func createACLServiceV2(c *cfg, apeSvc *objectAPE.Service, irFetcher *cachedIRFetcher) v2.Service {
|
func createACLServiceV2(c *cfg, apeSvc *objectAPE.Service, irFetcher *cachedIRFetcher) v2.Service {
|
||||||
ls := c.cfgObject.cfgLocalStorage.localStorage
|
|
||||||
|
|
||||||
return v2.New(
|
return v2.New(
|
||||||
apeSvc,
|
apeSvc,
|
||||||
c.netMapSource,
|
c.netMapSource,
|
||||||
irFetcher,
|
irFetcher,
|
||||||
acl.NewChecker(
|
|
||||||
c.cfgNetmap.state,
|
|
||||||
c.cfgObject.eaclSource,
|
|
||||||
eaclSDK.NewValidator(),
|
|
||||||
ls),
|
|
||||||
c.cfgObject.cnrSource,
|
c.cfgObject.cnrSource,
|
||||||
v2.WithLogger(c.log),
|
v2.WithLogger(c.log),
|
||||||
)
|
)
|
||||||
|
|
|
@ -44,9 +44,6 @@ type CheckPrm struct {
|
||||||
|
|
||||||
// The request's bearer token. It is used in order to check APE overrides with the token.
|
// The request's bearer token. It is used in order to check APE overrides with the token.
|
||||||
BearerToken *bearer.Token
|
BearerToken *bearer.Token
|
||||||
|
|
||||||
// If SoftAPECheck is set to true, then NoRuleFound is interpreted as allow.
|
|
||||||
SoftAPECheck bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckCore provides methods to perform the common logic of APE check.
|
// CheckCore provides methods to perform the common logic of APE check.
|
||||||
|
@ -104,7 +101,7 @@ func (c *checkerCoreImpl) CheckAPE(prm CheckPrm) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !found && prm.SoftAPECheck || status == apechain.Allow {
|
if found && status == apechain.Allow {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
err = fmt.Errorf("access to operation %s is denied by access policy engine: %s", prm.Request.Operation(), status.String())
|
err = fmt.Errorf("access to operation %s is denied by access policy engine: %s", prm.Request.Operation(), status.String())
|
||||||
|
|
|
@ -1,262 +0,0 @@
|
||||||
package acl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine"
|
|
||||||
eaclV2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/eacl/v2"
|
|
||||||
v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2"
|
|
||||||
bearerSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl"
|
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
||||||
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
|
|
||||||
eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
|
||||||
objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Checker implements v2.ACLChecker interfaces and provides
|
|
||||||
// ACL/eACL validation functionality.
|
|
||||||
type Checker struct {
|
|
||||||
eaclSrc container.EACLSource
|
|
||||||
validator *eaclSDK.Validator
|
|
||||||
localStorage *engine.StorageEngine
|
|
||||||
state netmap.State
|
|
||||||
}
|
|
||||||
|
|
||||||
type localStorage struct {
|
|
||||||
ls *engine.StorageEngine
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *localStorage) Head(ctx context.Context, addr oid.Address) (*objectSDK.Object, error) {
|
|
||||||
if s.ls == nil {
|
|
||||||
return nil, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
|
|
||||||
return engine.Head(ctx, s.ls, addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Various EACL check errors.
|
|
||||||
var (
|
|
||||||
errEACLDeniedByRule = errors.New("denied by rule")
|
|
||||||
errBearerExpired = errors.New("bearer token has expired")
|
|
||||||
errBearerInvalidSignature = errors.New("bearer token has invalid signature")
|
|
||||||
errBearerInvalidContainerID = errors.New("bearer token was created for another container")
|
|
||||||
errBearerNotSignedByOwner = errors.New("bearer token is not signed by the container owner")
|
|
||||||
errBearerInvalidOwner = errors.New("bearer token owner differs from the request sender")
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewChecker creates Checker.
|
|
||||||
// Panics if at least one of the parameter is nil.
|
|
||||||
func NewChecker(
|
|
||||||
state netmap.State,
|
|
||||||
eaclSrc container.EACLSource,
|
|
||||||
validator *eaclSDK.Validator,
|
|
||||||
localStorage *engine.StorageEngine,
|
|
||||||
) *Checker {
|
|
||||||
return &Checker{
|
|
||||||
eaclSrc: eaclSrc,
|
|
||||||
validator: validator,
|
|
||||||
localStorage: localStorage,
|
|
||||||
state: state,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckBasicACL is a main check function for basic ACL.
|
|
||||||
func (c *Checker) CheckBasicACL(info v2.RequestInfo) bool {
|
|
||||||
// check basic ACL permissions
|
|
||||||
return info.BasicACL().IsOpAllowed(info.Operation(), info.RequestRole())
|
|
||||||
}
|
|
||||||
|
|
||||||
// StickyBitCheck validates owner field in the request if sticky bit is enabled.
|
|
||||||
func (c *Checker) StickyBitCheck(info v2.RequestInfo, owner user.ID) bool {
|
|
||||||
// According to FrostFS specification sticky bit has no effect on system nodes
|
|
||||||
// for correct intra-container work with objects (in particular, replication).
|
|
||||||
if info.RequestRole() == acl.RoleContainer {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if !info.BasicACL().Sticky() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(info.SenderKey()) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
requestSenderKey := unmarshalPublicKey(info.SenderKey())
|
|
||||||
|
|
||||||
return isOwnerFromKey(owner, requestSenderKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckEACL is a main check function for extended ACL.
|
|
||||||
func (c *Checker) CheckEACL(msg any, reqInfo v2.RequestInfo) error {
|
|
||||||
basicACL := reqInfo.BasicACL()
|
|
||||||
if !basicACL.Extendable() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
bearerTok := reqInfo.Bearer()
|
|
||||||
impersonate := bearerTok != nil && bearerTok.Impersonate()
|
|
||||||
|
|
||||||
// if bearer token is not allowed, then ignore it
|
|
||||||
if impersonate || !basicACL.AllowedBearerRules(reqInfo.Operation()) {
|
|
||||||
reqInfo.CleanBearer()
|
|
||||||
}
|
|
||||||
|
|
||||||
var table eaclSDK.Table
|
|
||||||
cnr := reqInfo.ContainerID()
|
|
||||||
|
|
||||||
if bearerTok == nil {
|
|
||||||
eaclInfo, err := c.eaclSrc.GetEACL(cnr)
|
|
||||||
if err != nil {
|
|
||||||
if client.IsErrEACLNotFound(err) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
table = *eaclInfo.Value
|
|
||||||
} else {
|
|
||||||
table = bearerTok.EACLTable()
|
|
||||||
}
|
|
||||||
|
|
||||||
// if bearer token is not present, isValidBearer returns true
|
|
||||||
if err := isValidBearer(reqInfo, c.state); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
hdrSrc, err := c.getHeaderSource(cnr, msg, reqInfo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
eaclRole := getRole(reqInfo)
|
|
||||||
|
|
||||||
action, _ := c.validator.CalculateAction(new(eaclSDK.ValidationUnit).
|
|
||||||
WithRole(eaclRole).
|
|
||||||
WithOperation(eaclSDK.Operation(reqInfo.Operation())).
|
|
||||||
WithContainerID(&cnr).
|
|
||||||
WithSenderKey(reqInfo.SenderKey()).
|
|
||||||
WithHeaderSource(hdrSrc).
|
|
||||||
WithEACLTable(&table),
|
|
||||||
)
|
|
||||||
|
|
||||||
if action != eaclSDK.ActionAllow {
|
|
||||||
return errEACLDeniedByRule
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRole(reqInfo v2.RequestInfo) eaclSDK.Role {
|
|
||||||
var eaclRole eaclSDK.Role
|
|
||||||
switch op := reqInfo.RequestRole(); op {
|
|
||||||
default:
|
|
||||||
eaclRole = eaclSDK.Role(op)
|
|
||||||
case acl.RoleOwner:
|
|
||||||
eaclRole = eaclSDK.RoleUser
|
|
||||||
case acl.RoleInnerRing, acl.RoleContainer:
|
|
||||||
eaclRole = eaclSDK.RoleSystem
|
|
||||||
case acl.RoleOthers:
|
|
||||||
eaclRole = eaclSDK.RoleOthers
|
|
||||||
}
|
|
||||||
return eaclRole
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Checker) getHeaderSource(cnr cid.ID, msg any, reqInfo v2.RequestInfo) (eaclSDK.TypedHeaderSource, error) {
|
|
||||||
var xHeaderSource eaclV2.XHeaderSource
|
|
||||||
if req, ok := msg.(eaclV2.Request); ok {
|
|
||||||
xHeaderSource = eaclV2.NewRequestXHeaderSource(req)
|
|
||||||
} else {
|
|
||||||
xHeaderSource = eaclV2.NewResponseXHeaderSource(msg.(eaclV2.Response), reqInfo.Request().(eaclV2.Request))
|
|
||||||
}
|
|
||||||
|
|
||||||
hdrSrc, err := eaclV2.NewMessageHeaderSource(&localStorage{ls: c.localStorage}, xHeaderSource, cnr, eaclV2.WithOID(reqInfo.ObjectID()))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("can't parse headers: %w", err)
|
|
||||||
}
|
|
||||||
return hdrSrc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// isValidBearer checks whether bearer token was correctly signed by authorized
|
|
||||||
// entity. This method might be defined on whole ACL service because it will
|
|
||||||
// require fetching current epoch to check lifetime.
|
|
||||||
func isValidBearer(reqInfo v2.RequestInfo, st netmap.State) error {
|
|
||||||
ownerCnr := reqInfo.ContainerOwner()
|
|
||||||
|
|
||||||
token := reqInfo.Bearer()
|
|
||||||
|
|
||||||
// 0. Check if bearer token is present in reqInfo.
|
|
||||||
if token == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. First check token lifetime. Simplest verification.
|
|
||||||
if token.InvalidAt(st.CurrentEpoch()) {
|
|
||||||
return errBearerExpired
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Then check if bearer token is signed correctly.
|
|
||||||
if !token.VerifySignature() {
|
|
||||||
return errBearerInvalidSignature
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Then check if container is either empty or equal to the container in the request.
|
|
||||||
cnr, isSet := token.EACLTable().CID()
|
|
||||||
if isSet && !cnr.Equals(reqInfo.ContainerID()) {
|
|
||||||
return errBearerInvalidContainerID
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Then check if container owner signed this token.
|
|
||||||
if !bearerSDK.ResolveIssuer(*token).Equals(ownerCnr) {
|
|
||||||
// TODO: #767 in this case we can issue all owner keys from frostfs.id and check once again
|
|
||||||
return errBearerNotSignedByOwner
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. Then check if request sender has rights to use this token.
|
|
||||||
var keySender frostfsecdsa.PublicKey
|
|
||||||
|
|
||||||
err := keySender.Decode(reqInfo.SenderKey())
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("decode sender public key: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var usrSender user.ID
|
|
||||||
user.IDFromKey(&usrSender, ecdsa.PublicKey(keySender))
|
|
||||||
|
|
||||||
if !token.AssertUser(usrSender) {
|
|
||||||
// TODO: #767 in this case we can issue all owner keys from frostfs.id and check once again
|
|
||||||
return errBearerInvalidOwner
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func isOwnerFromKey(id user.ID, key *keys.PublicKey) bool {
|
|
||||||
if key == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var id2 user.ID
|
|
||||||
user.IDFromKey(&id2, (ecdsa.PublicKey)(*key))
|
|
||||||
|
|
||||||
return id.Equals(id2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func unmarshalPublicKey(bs []byte) *keys.PublicKey {
|
|
||||||
pub, err := keys.NewPublicKeyFromBytes(bs, elliptic.P256())
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return pub
|
|
||||||
}
|
|
|
@ -1,89 +0,0 @@
|
||||||
package acl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/engine"
|
|
||||||
v2 "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/acl/v2"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl"
|
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
||||||
eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
|
||||||
usertest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user/test"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
type emptyEACLSource struct{}
|
|
||||||
|
|
||||||
func (e emptyEACLSource) GetEACL(_ cid.ID) (*container.EACL, error) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type emptyNetmapState struct{}
|
|
||||||
|
|
||||||
func (e emptyNetmapState) CurrentEpoch() uint64 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestStickyCheck(t *testing.T) {
|
|
||||||
checker := NewChecker(
|
|
||||||
emptyNetmapState{},
|
|
||||||
emptyEACLSource{},
|
|
||||||
eaclSDK.NewValidator(),
|
|
||||||
&engine.StorageEngine{})
|
|
||||||
|
|
||||||
t.Run("system role", func(t *testing.T) {
|
|
||||||
var info v2.RequestInfo
|
|
||||||
|
|
||||||
info.SetSenderKey(make([]byte, 33)) // any non-empty key
|
|
||||||
info.SetRequestRole(acl.RoleContainer)
|
|
||||||
|
|
||||||
require.True(t, checker.StickyBitCheck(info, usertest.ID()))
|
|
||||||
|
|
||||||
var basicACL acl.Basic
|
|
||||||
basicACL.MakeSticky()
|
|
||||||
|
|
||||||
info.SetBasicACL(basicACL)
|
|
||||||
|
|
||||||
require.True(t, checker.StickyBitCheck(info, usertest.ID()))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("owner ID and/or public key emptiness", func(t *testing.T) {
|
|
||||||
var info v2.RequestInfo
|
|
||||||
|
|
||||||
info.SetRequestRole(acl.RoleOthers) // should be non-system role
|
|
||||||
|
|
||||||
assertFn := func(isSticky, withKey, withOwner, expected bool) {
|
|
||||||
info := info
|
|
||||||
if isSticky {
|
|
||||||
var basicACL acl.Basic
|
|
||||||
basicACL.MakeSticky()
|
|
||||||
|
|
||||||
info.SetBasicACL(basicACL)
|
|
||||||
}
|
|
||||||
|
|
||||||
if withKey {
|
|
||||||
info.SetSenderKey(make([]byte, 33))
|
|
||||||
} else {
|
|
||||||
info.SetSenderKey(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
var ownerID user.ID
|
|
||||||
|
|
||||||
if withOwner {
|
|
||||||
ownerID = usertest.ID()
|
|
||||||
}
|
|
||||||
|
|
||||||
require.Equal(t, expected, checker.StickyBitCheck(info, ownerID))
|
|
||||||
}
|
|
||||||
|
|
||||||
assertFn(true, false, false, false)
|
|
||||||
assertFn(true, true, false, false)
|
|
||||||
assertFn(true, false, true, false)
|
|
||||||
assertFn(false, false, false, true)
|
|
||||||
assertFn(false, true, false, true)
|
|
||||||
assertFn(false, false, true, true)
|
|
||||||
assertFn(false, true, true, true)
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -2,8 +2,6 @@ package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const invalidRequestMessage = "malformed request"
|
const invalidRequestMessage = "malformed request"
|
||||||
|
@ -20,22 +18,3 @@ var (
|
||||||
errInvalidSessionOwner = malformedRequestError("invalid session token owner")
|
errInvalidSessionOwner = malformedRequestError("invalid session token owner")
|
||||||
errInvalidVerb = malformedRequestError("session token verb is invalid")
|
errInvalidVerb = malformedRequestError("session token verb is invalid")
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
accessDeniedACLReasonFmt = "access to operation %s is denied by basic ACL check"
|
|
||||||
accessDeniedEACLReasonFmt = "access to operation %s is denied by extended ACL check: %v"
|
|
||||||
)
|
|
||||||
|
|
||||||
func basicACLErr(info RequestInfo) error {
|
|
||||||
errAccessDenied := &apistatus.ObjectAccessDenied{}
|
|
||||||
errAccessDenied.WriteReason(fmt.Sprintf(accessDeniedACLReasonFmt, info.operation))
|
|
||||||
|
|
||||||
return errAccessDenied
|
|
||||||
}
|
|
||||||
|
|
||||||
func eACLErr(info RequestInfo, err error) error {
|
|
||||||
errAccessDenied := &apistatus.ObjectAccessDenied{}
|
|
||||||
errAccessDenied.WriteReason(fmt.Sprintf(accessDeniedEACLReasonFmt, info.operation, err))
|
|
||||||
|
|
||||||
return errAccessDenied
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
package v2
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBasicACLErr(t *testing.T) {
|
|
||||||
var reqInfo RequestInfo
|
|
||||||
err := basicACLErr(reqInfo)
|
|
||||||
|
|
||||||
var errAccessDenied *apistatus.ObjectAccessDenied
|
|
||||||
|
|
||||||
require.ErrorAs(t, err, &errAccessDenied,
|
|
||||||
"basicACLErr must be able to be casted to apistatus.ObjectAccessDenied")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEACLErr(t *testing.T) {
|
|
||||||
var reqInfo RequestInfo
|
|
||||||
testErr := errors.New("test-eacl")
|
|
||||||
err := eACLErr(reqInfo, testErr)
|
|
||||||
|
|
||||||
var errAccessDenied *apistatus.ObjectAccessDenied
|
|
||||||
|
|
||||||
require.ErrorAs(t, err, &errAccessDenied,
|
|
||||||
"eACLErr must be able to be casted to apistatus.ObjectAccessDenied")
|
|
||||||
}
|
|
|
@ -104,13 +104,6 @@ func (r RequestInfo) RequestRole() acl.Role {
|
||||||
return r.requestRole
|
return r.requestRole
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsSoftAPECheck states if APE should perform soft checks.
|
|
||||||
// Soft APE check allows a request if CheckAPE returns NoRuleFound for it,
|
|
||||||
// otherwise it denies the request.
|
|
||||||
func (r RequestInfo) IsSoftAPECheck() bool {
|
|
||||||
return r.BasicACL().Bits() != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// MetaWithToken groups session and bearer tokens,
|
// MetaWithToken groups session and bearer tokens,
|
||||||
// verification header and raw API request.
|
// verification header and raw API request.
|
||||||
type MetaWithToken struct {
|
type MetaWithToken struct {
|
||||||
|
|
|
@ -41,30 +41,6 @@ type patchStreamBasicChecker struct {
|
||||||
nonFirstSend bool
|
nonFirstSend bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type getStreamBasicChecker struct {
|
|
||||||
checker ACLChecker
|
|
||||||
|
|
||||||
object.GetObjectStream
|
|
||||||
|
|
||||||
info RequestInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
type rangeStreamBasicChecker struct {
|
|
||||||
checker ACLChecker
|
|
||||||
|
|
||||||
object.GetObjectRangeStream
|
|
||||||
|
|
||||||
info RequestInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
type searchStreamBasicChecker struct {
|
|
||||||
checker ACLChecker
|
|
||||||
|
|
||||||
object.SearchStream
|
|
||||||
|
|
||||||
info RequestInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// Option represents Service constructor option.
|
// Option represents Service constructor option.
|
||||||
type Option func(*cfg)
|
type Option func(*cfg)
|
||||||
|
|
||||||
|
@ -73,8 +49,6 @@ type cfg struct {
|
||||||
|
|
||||||
containers container.Source
|
containers container.Source
|
||||||
|
|
||||||
checker ACLChecker
|
|
||||||
|
|
||||||
irFetcher InnerRingFetcher
|
irFetcher InnerRingFetcher
|
||||||
|
|
||||||
nm netmap.Source
|
nm netmap.Source
|
||||||
|
@ -86,7 +60,6 @@ type cfg struct {
|
||||||
func New(next object.ServiceServer,
|
func New(next object.ServiceServer,
|
||||||
nm netmap.Source,
|
nm netmap.Source,
|
||||||
irf InnerRingFetcher,
|
irf InnerRingFetcher,
|
||||||
acl ACLChecker,
|
|
||||||
cs container.Source,
|
cs container.Source,
|
||||||
opts ...Option,
|
opts ...Option,
|
||||||
) Service {
|
) Service {
|
||||||
|
@ -95,7 +68,6 @@ func New(next object.ServiceServer,
|
||||||
next: next,
|
next: next,
|
||||||
nm: nm,
|
nm: nm,
|
||||||
irFetcher: irf,
|
irFetcher: irf,
|
||||||
checker: acl,
|
|
||||||
containers: cs,
|
containers: cs,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +95,6 @@ func (w *wrappedGetObjectStream) Context() context.Context {
|
||||||
ContainerOwner: w.requestInfo.ContainerOwner(),
|
ContainerOwner: w.requestInfo.ContainerOwner(),
|
||||||
SenderKey: w.requestInfo.SenderKey(),
|
SenderKey: w.requestInfo.SenderKey(),
|
||||||
Role: w.requestInfo.RequestRole(),
|
Role: w.requestInfo.RequestRole(),
|
||||||
SoftAPECheck: w.requestInfo.IsSoftAPECheck(),
|
|
||||||
BearerToken: w.requestInfo.Bearer(),
|
BearerToken: w.requestInfo.Bearer(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -149,7 +120,6 @@ func (w *wrappedRangeStream) Context() context.Context {
|
||||||
ContainerOwner: w.requestInfo.ContainerOwner(),
|
ContainerOwner: w.requestInfo.ContainerOwner(),
|
||||||
SenderKey: w.requestInfo.SenderKey(),
|
SenderKey: w.requestInfo.SenderKey(),
|
||||||
Role: w.requestInfo.RequestRole(),
|
Role: w.requestInfo.RequestRole(),
|
||||||
SoftAPECheck: w.requestInfo.IsSoftAPECheck(),
|
|
||||||
BearerToken: w.requestInfo.Bearer(),
|
BearerToken: w.requestInfo.Bearer(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -175,7 +145,6 @@ func (w *wrappedSearchStream) Context() context.Context {
|
||||||
ContainerOwner: w.requestInfo.ContainerOwner(),
|
ContainerOwner: w.requestInfo.ContainerOwner(),
|
||||||
SenderKey: w.requestInfo.SenderKey(),
|
SenderKey: w.requestInfo.SenderKey(),
|
||||||
Role: w.requestInfo.RequestRole(),
|
Role: w.requestInfo.RequestRole(),
|
||||||
SoftAPECheck: w.requestInfo.IsSoftAPECheck(),
|
|
||||||
BearerToken: w.requestInfo.Bearer(),
|
BearerToken: w.requestInfo.Bearer(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -231,19 +200,7 @@ func (b Service) Get(request *objectV2.GetRequest, stream object.GetObjectStream
|
||||||
|
|
||||||
reqInfo.obj = obj
|
reqInfo.obj = obj
|
||||||
|
|
||||||
if reqInfo.IsSoftAPECheck() {
|
return b.next.Get(request, newWrappedGetObjectStreamStream(stream, reqInfo))
|
||||||
if !b.checker.CheckBasicACL(reqInfo) {
|
|
||||||
return basicACLErr(reqInfo)
|
|
||||||
} else if err := b.checker.CheckEACL(request, reqInfo); err != nil {
|
|
||||||
return eACLErr(reqInfo, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.next.Get(request, &getStreamBasicChecker{
|
|
||||||
GetObjectStream: newWrappedGetObjectStreamStream(stream, reqInfo),
|
|
||||||
info: reqInfo,
|
|
||||||
checker: b.checker,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Service) Put() (object.PutObjectStream, error) {
|
func (b Service) Put() (object.PutObjectStream, error) {
|
||||||
|
@ -309,22 +266,7 @@ func (b Service) Head(
|
||||||
|
|
||||||
reqInfo.obj = obj
|
reqInfo.obj = obj
|
||||||
|
|
||||||
if reqInfo.IsSoftAPECheck() {
|
return b.next.Head(requestContext(ctx, reqInfo), request)
|
||||||
if !b.checker.CheckBasicACL(reqInfo) {
|
|
||||||
return nil, basicACLErr(reqInfo)
|
|
||||||
} else if err := b.checker.CheckEACL(request, reqInfo); err != nil {
|
|
||||||
return nil, eACLErr(reqInfo, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := b.next.Head(requestContext(ctx, reqInfo), request)
|
|
||||||
if err == nil {
|
|
||||||
if err = b.checker.CheckEACL(resp, reqInfo); err != nil {
|
|
||||||
err = eACLErr(reqInfo, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStream) error {
|
func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStream) error {
|
||||||
|
@ -362,19 +304,7 @@ func (b Service) Search(request *objectV2.SearchRequest, stream object.SearchStr
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if reqInfo.IsSoftAPECheck() {
|
return b.next.Search(request, newWrappedSearchStream(stream, reqInfo))
|
||||||
if !b.checker.CheckBasicACL(reqInfo) {
|
|
||||||
return basicACLErr(reqInfo)
|
|
||||||
} else if err := b.checker.CheckEACL(request, reqInfo); err != nil {
|
|
||||||
return eACLErr(reqInfo, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.next.Search(request, &searchStreamBasicChecker{
|
|
||||||
checker: b.checker,
|
|
||||||
SearchStream: newWrappedSearchStream(stream, reqInfo),
|
|
||||||
info: reqInfo,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Service) Delete(
|
func (b Service) Delete(
|
||||||
|
@ -422,14 +352,6 @@ func (b Service) Delete(
|
||||||
|
|
||||||
reqInfo.obj = obj
|
reqInfo.obj = obj
|
||||||
|
|
||||||
if reqInfo.IsSoftAPECheck() {
|
|
||||||
if !b.checker.CheckBasicACL(reqInfo) {
|
|
||||||
return nil, basicACLErr(reqInfo)
|
|
||||||
} else if err := b.checker.CheckEACL(request, reqInfo); err != nil {
|
|
||||||
return nil, eACLErr(reqInfo, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.next.Delete(requestContext(ctx, reqInfo), request)
|
return b.next.Delete(requestContext(ctx, reqInfo), request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,19 +397,7 @@ func (b Service) GetRange(request *objectV2.GetRangeRequest, stream object.GetOb
|
||||||
|
|
||||||
reqInfo.obj = obj
|
reqInfo.obj = obj
|
||||||
|
|
||||||
if reqInfo.IsSoftAPECheck() {
|
return b.next.GetRange(request, newWrappedRangeStream(stream, reqInfo))
|
||||||
if !b.checker.CheckBasicACL(reqInfo) {
|
|
||||||
return basicACLErr(reqInfo)
|
|
||||||
} else if err := b.checker.CheckEACL(request, reqInfo); err != nil {
|
|
||||||
return eACLErr(reqInfo, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.next.GetRange(request, &rangeStreamBasicChecker{
|
|
||||||
checker: b.checker,
|
|
||||||
GetObjectRangeStream: newWrappedRangeStream(stream, reqInfo),
|
|
||||||
info: reqInfo,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestContext(ctx context.Context, reqInfo RequestInfo) context.Context {
|
func requestContext(ctx context.Context, reqInfo RequestInfo) context.Context {
|
||||||
|
@ -496,7 +406,6 @@ func requestContext(ctx context.Context, reqInfo RequestInfo) context.Context {
|
||||||
ContainerOwner: reqInfo.ContainerOwner(),
|
ContainerOwner: reqInfo.ContainerOwner(),
|
||||||
SenderKey: reqInfo.SenderKey(),
|
SenderKey: reqInfo.SenderKey(),
|
||||||
Role: reqInfo.RequestRole(),
|
Role: reqInfo.RequestRole(),
|
||||||
SoftAPECheck: reqInfo.IsSoftAPECheck(),
|
|
||||||
BearerToken: reqInfo.Bearer(),
|
BearerToken: reqInfo.Bearer(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -546,14 +455,6 @@ func (b Service) GetRangeHash(
|
||||||
|
|
||||||
reqInfo.obj = obj
|
reqInfo.obj = obj
|
||||||
|
|
||||||
if reqInfo.IsSoftAPECheck() {
|
|
||||||
if !b.checker.CheckBasicACL(reqInfo) {
|
|
||||||
return nil, basicACLErr(reqInfo)
|
|
||||||
} else if err := b.checker.CheckEACL(request, reqInfo); err != nil {
|
|
||||||
return nil, eACLErr(reqInfo, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.next.GetRangeHash(requestContext(ctx, reqInfo), request)
|
return b.next.GetRangeHash(requestContext(ctx, reqInfo), request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -605,15 +506,6 @@ func (b Service) PutSingle(ctx context.Context, request *objectV2.PutSingleReque
|
||||||
|
|
||||||
reqInfo.obj = obj
|
reqInfo.obj = obj
|
||||||
|
|
||||||
if reqInfo.IsSoftAPECheck() {
|
|
||||||
if !b.checker.CheckBasicACL(reqInfo) || !b.checker.StickyBitCheck(reqInfo, idOwner) {
|
|
||||||
return nil, basicACLErr(reqInfo)
|
|
||||||
}
|
|
||||||
if err := b.checker.CheckEACL(request, reqInfo); err != nil {
|
|
||||||
return nil, eACLErr(reqInfo, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.next.PutSingle(requestContext(ctx, reqInfo), request)
|
return b.next.PutSingle(requestContext(ctx, reqInfo), request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,12 +571,6 @@ func (p putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutRe
|
||||||
|
|
||||||
reqInfo.obj = obj
|
reqInfo.obj = obj
|
||||||
|
|
||||||
if reqInfo.IsSoftAPECheck() {
|
|
||||||
if !p.source.checker.CheckBasicACL(reqInfo) || !p.source.checker.StickyBitCheck(reqInfo, idOwner) {
|
|
||||||
return basicACLErr(reqInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = requestContext(ctx, reqInfo)
|
ctx = requestContext(ctx, reqInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,32 +609,6 @@ func (p putStreamBasicChecker) CloseAndRecv(ctx context.Context) (*objectV2.PutR
|
||||||
return p.next.CloseAndRecv(ctx)
|
return p.next.CloseAndRecv(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error {
|
|
||||||
if _, ok := resp.GetBody().GetObjectPart().(*objectV2.GetObjectPartInit); ok {
|
|
||||||
if err := g.checker.CheckEACL(resp, g.info); err != nil {
|
|
||||||
return eACLErr(g.info, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return g.GetObjectStream.Send(resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *rangeStreamBasicChecker) Send(resp *objectV2.GetRangeResponse) error {
|
|
||||||
if err := g.checker.CheckEACL(resp, g.info); err != nil {
|
|
||||||
return eACLErr(g.info, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return g.GetObjectRangeStream.Send(resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *searchStreamBasicChecker) Send(resp *objectV2.SearchResponse) error {
|
|
||||||
if err := g.checker.CheckEACL(resp, g.info); err != nil {
|
|
||||||
return eACLErr(g.info, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return g.SearchStream.Send(resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.PatchRequest) error {
|
func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.PatchRequest) error {
|
||||||
body := request.GetBody()
|
body := request.GetBody()
|
||||||
if body == nil {
|
if body == nil {
|
||||||
|
|
|
@ -1,24 +1,5 @@
|
||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ACLChecker is an interface that must provide
|
|
||||||
// ACL related checks.
|
|
||||||
type ACLChecker interface {
|
|
||||||
// CheckBasicACL must return true only if request
|
|
||||||
// passes basic ACL validation.
|
|
||||||
CheckBasicACL(RequestInfo) bool
|
|
||||||
// CheckEACL must return non-nil error if request
|
|
||||||
// doesn't pass extended ACL validation.
|
|
||||||
CheckEACL(any, RequestInfo) error
|
|
||||||
// StickyBitCheck must return true only if sticky bit
|
|
||||||
// is disabled or enabled but request contains correct
|
|
||||||
// owner field.
|
|
||||||
StickyBitCheck(RequestInfo, user.ID) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// InnerRingFetcher is an interface that must provide
|
// InnerRingFetcher is an interface that must provide
|
||||||
// Inner Ring information.
|
// Inner Ring information.
|
||||||
type InnerRingFetcher interface {
|
type InnerRingFetcher interface {
|
||||||
|
|
|
@ -64,9 +64,6 @@ type Prm struct {
|
||||||
// An encoded container's owner user ID.
|
// An encoded container's owner user ID.
|
||||||
ContainerOwner user.ID
|
ContainerOwner user.ID
|
||||||
|
|
||||||
// If SoftAPECheck is set to true, then NoRuleFound is interpreted as allow.
|
|
||||||
SoftAPECheck bool
|
|
||||||
|
|
||||||
// The request's bearer token. It is used in order to check APE overrides with the token.
|
// The request's bearer token. It is used in order to check APE overrides with the token.
|
||||||
BearerToken *bearer.Token
|
BearerToken *bearer.Token
|
||||||
|
|
||||||
|
@ -109,6 +106,5 @@ func (c *checkerImpl) CheckAPE(ctx context.Context, prm Prm) error {
|
||||||
Container: prm.Container,
|
Container: prm.Container,
|
||||||
ContainerOwner: prm.ContainerOwner,
|
ContainerOwner: prm.ContainerOwner,
|
||||||
BearerToken: prm.BearerToken,
|
BearerToken: prm.BearerToken,
|
||||||
SoftAPECheck: prm.SoftAPECheck,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,8 +84,6 @@ type getStreamBasicChecker struct {
|
||||||
|
|
||||||
role string
|
role string
|
||||||
|
|
||||||
softAPECheck bool
|
|
||||||
|
|
||||||
bearerToken *bearer.Token
|
bearerToken *bearer.Token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +103,6 @@ func (g *getStreamBasicChecker) Send(resp *objectV2.GetResponse) error {
|
||||||
SenderKey: hex.EncodeToString(g.senderKey),
|
SenderKey: hex.EncodeToString(g.senderKey),
|
||||||
ContainerOwner: g.containerOwner,
|
ContainerOwner: g.containerOwner,
|
||||||
Role: g.role,
|
Role: g.role,
|
||||||
SoftAPECheck: g.softAPECheck,
|
|
||||||
BearerToken: g.bearerToken,
|
BearerToken: g.bearerToken,
|
||||||
XHeaders: resp.GetMetaHeader().GetXHeaders(),
|
XHeaders: resp.GetMetaHeader().GetXHeaders(),
|
||||||
}
|
}
|
||||||
|
@ -142,7 +139,6 @@ func (c *Service) Get(request *objectV2.GetRequest, stream objectSvc.GetObjectSt
|
||||||
senderKey: reqCtx.SenderKey,
|
senderKey: reqCtx.SenderKey,
|
||||||
containerOwner: reqCtx.ContainerOwner,
|
containerOwner: reqCtx.ContainerOwner,
|
||||||
role: nativeSchemaRole(reqCtx.Role),
|
role: nativeSchemaRole(reqCtx.Role),
|
||||||
softAPECheck: reqCtx.SoftAPECheck,
|
|
||||||
bearerToken: reqCtx.BearerToken,
|
bearerToken: reqCtx.BearerToken,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -174,7 +170,6 @@ func (p *putStreamBasicChecker) Send(ctx context.Context, request *objectV2.PutR
|
||||||
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
||||||
ContainerOwner: reqCtx.ContainerOwner,
|
ContainerOwner: reqCtx.ContainerOwner,
|
||||||
Role: nativeSchemaRole(reqCtx.Role),
|
Role: nativeSchemaRole(reqCtx.Role),
|
||||||
SoftAPECheck: reqCtx.SoftAPECheck,
|
|
||||||
BearerToken: reqCtx.BearerToken,
|
BearerToken: reqCtx.BearerToken,
|
||||||
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
||||||
}
|
}
|
||||||
|
@ -230,7 +225,6 @@ func (p *patchStreamBasicChecker) Send(ctx context.Context, request *objectV2.Pa
|
||||||
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
||||||
ContainerOwner: reqCtx.ContainerOwner,
|
ContainerOwner: reqCtx.ContainerOwner,
|
||||||
Role: nativeSchemaRole(reqCtx.Role),
|
Role: nativeSchemaRole(reqCtx.Role),
|
||||||
SoftAPECheck: reqCtx.SoftAPECheck,
|
|
||||||
BearerToken: reqCtx.BearerToken,
|
BearerToken: reqCtx.BearerToken,
|
||||||
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
||||||
}
|
}
|
||||||
|
@ -300,7 +294,6 @@ func (c *Service) Head(ctx context.Context, request *objectV2.HeadRequest) (*obj
|
||||||
Role: nativeSchemaRole(reqCtx.Role),
|
Role: nativeSchemaRole(reqCtx.Role),
|
||||||
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
||||||
ContainerOwner: reqCtx.ContainerOwner,
|
ContainerOwner: reqCtx.ContainerOwner,
|
||||||
SoftAPECheck: reqCtx.SoftAPECheck,
|
|
||||||
BearerToken: reqCtx.BearerToken,
|
BearerToken: reqCtx.BearerToken,
|
||||||
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
||||||
})
|
})
|
||||||
|
@ -330,7 +323,6 @@ func (c *Service) Search(request *objectV2.SearchRequest, stream objectSvc.Searc
|
||||||
Role: nativeSchemaRole(reqCtx.Role),
|
Role: nativeSchemaRole(reqCtx.Role),
|
||||||
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
||||||
ContainerOwner: reqCtx.ContainerOwner,
|
ContainerOwner: reqCtx.ContainerOwner,
|
||||||
SoftAPECheck: reqCtx.SoftAPECheck,
|
|
||||||
BearerToken: reqCtx.BearerToken,
|
BearerToken: reqCtx.BearerToken,
|
||||||
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
||||||
})
|
})
|
||||||
|
@ -360,7 +352,6 @@ func (c *Service) Delete(ctx context.Context, request *objectV2.DeleteRequest) (
|
||||||
Role: nativeSchemaRole(reqCtx.Role),
|
Role: nativeSchemaRole(reqCtx.Role),
|
||||||
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
||||||
ContainerOwner: reqCtx.ContainerOwner,
|
ContainerOwner: reqCtx.ContainerOwner,
|
||||||
SoftAPECheck: reqCtx.SoftAPECheck,
|
|
||||||
BearerToken: reqCtx.BearerToken,
|
BearerToken: reqCtx.BearerToken,
|
||||||
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
||||||
})
|
})
|
||||||
|
@ -395,7 +386,6 @@ func (c *Service) GetRange(request *objectV2.GetRangeRequest, stream objectSvc.G
|
||||||
Role: nativeSchemaRole(reqCtx.Role),
|
Role: nativeSchemaRole(reqCtx.Role),
|
||||||
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
||||||
ContainerOwner: reqCtx.ContainerOwner,
|
ContainerOwner: reqCtx.ContainerOwner,
|
||||||
SoftAPECheck: reqCtx.SoftAPECheck,
|
|
||||||
BearerToken: reqCtx.BearerToken,
|
BearerToken: reqCtx.BearerToken,
|
||||||
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
||||||
})
|
})
|
||||||
|
@ -425,7 +415,6 @@ func (c *Service) GetRangeHash(ctx context.Context, request *objectV2.GetRangeHa
|
||||||
Role: nativeSchemaRole(reqCtx.Role),
|
Role: nativeSchemaRole(reqCtx.Role),
|
||||||
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
||||||
ContainerOwner: reqCtx.ContainerOwner,
|
ContainerOwner: reqCtx.ContainerOwner,
|
||||||
SoftAPECheck: reqCtx.SoftAPECheck,
|
|
||||||
BearerToken: reqCtx.BearerToken,
|
BearerToken: reqCtx.BearerToken,
|
||||||
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
||||||
}
|
}
|
||||||
|
@ -461,7 +450,6 @@ func (c *Service) PutSingle(ctx context.Context, request *objectV2.PutSingleRequ
|
||||||
Role: nativeSchemaRole(reqCtx.Role),
|
Role: nativeSchemaRole(reqCtx.Role),
|
||||||
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
SenderKey: hex.EncodeToString(reqCtx.SenderKey),
|
||||||
ContainerOwner: reqCtx.ContainerOwner,
|
ContainerOwner: reqCtx.ContainerOwner,
|
||||||
SoftAPECheck: reqCtx.SoftAPECheck,
|
|
||||||
BearerToken: reqCtx.BearerToken,
|
BearerToken: reqCtx.BearerToken,
|
||||||
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
XHeaders: request.GetMetaHeader().GetXHeaders(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,5 @@ type RequestContext struct {
|
||||||
|
|
||||||
Role acl.Role
|
Role acl.Role
|
||||||
|
|
||||||
SoftAPECheck bool
|
|
||||||
|
|
||||||
BearerToken *bearer.Token
|
BearerToken *bearer.Token
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,6 @@ func (s *Service) checkAPE(ctx context.Context, bt *bearer.Token,
|
||||||
ContainerOwner: container.Value.Owner(),
|
ContainerOwner: container.Value.Owner(),
|
||||||
PublicKey: publicKey,
|
PublicKey: publicKey,
|
||||||
BearerToken: bt,
|
BearerToken: bt,
|
||||||
SoftAPECheck: false,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue