forked from TrueCloudLab/frostfs-s3-gw
parent
3d0d2032c6
commit
d9d12debc3
5 changed files with 175 additions and 27 deletions
|
@ -299,31 +299,31 @@ func (h *handler) encodeBucketCannedACL(ctx context.Context, bktInfo *data.Bucke
|
||||||
DisplayName: ownerDisplayName,
|
DisplayName: ownerDisplayName,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
granteeOwner := NewGrantee(acpCanonicalUser)
|
||||||
|
granteeOwner.ID = ownerEncodedID
|
||||||
|
granteeOwner.DisplayName = ownerDisplayName
|
||||||
|
|
||||||
res.AccessControlList = []*Grant{{
|
res.AccessControlList = []*Grant{{
|
||||||
Grantee: &Grantee{
|
Grantee: granteeOwner,
|
||||||
ID: ownerEncodedID,
|
|
||||||
DisplayName: ownerDisplayName,
|
|
||||||
Type: acpCanonicalUser,
|
|
||||||
},
|
|
||||||
Permission: aclFullControl,
|
Permission: aclFullControl,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
switch settings.CannedACL {
|
switch settings.CannedACL {
|
||||||
case basicACLPublic:
|
case basicACLPublic:
|
||||||
|
grantee := NewGrantee(acpGroup)
|
||||||
|
grantee.URI = allUsersGroup
|
||||||
|
|
||||||
res.AccessControlList = append(res.AccessControlList, &Grant{
|
res.AccessControlList = append(res.AccessControlList, &Grant{
|
||||||
Grantee: &Grantee{
|
Grantee: grantee,
|
||||||
URI: allUsersGroup,
|
|
||||||
Type: acpGroup,
|
|
||||||
},
|
|
||||||
Permission: aclWrite,
|
Permission: aclWrite,
|
||||||
})
|
})
|
||||||
fallthrough
|
fallthrough
|
||||||
case basicACLReadOnly:
|
case basicACLReadOnly:
|
||||||
|
grantee := NewGrantee(acpGroup)
|
||||||
|
grantee.URI = allUsersGroup
|
||||||
|
|
||||||
res.AccessControlList = append(res.AccessControlList, &Grant{
|
res.AccessControlList = append(res.AccessControlList, &Grant{
|
||||||
Grantee: &Grantee{
|
Grantee: grantee,
|
||||||
URI: allUsersGroup,
|
|
||||||
Type: acpGroup,
|
|
||||||
},
|
|
||||||
Permission: aclRead,
|
Permission: aclRead,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
|
||||||
engineiam "git.frostfs.info/TrueCloudLab/policy-engine/iam"
|
engineiam "git.frostfs.info/TrueCloudLab/policy-engine/iam"
|
||||||
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
@ -1308,13 +1309,98 @@ func TestPutBucketACL(t *testing.T) {
|
||||||
bktInfo := createBucketOldACL(tc, bktName, box)
|
bktInfo := createBucketOldACL(tc, bktName, box)
|
||||||
|
|
||||||
header := map[string]string{api.AmzACL: "public-read"}
|
header := map[string]string{api.AmzACL: "public-read"}
|
||||||
putBucketACL(t, tc, bktName, box, header)
|
putBucketACL(tc, bktName, box, header)
|
||||||
|
|
||||||
header = map[string]string{api.AmzACL: "private"}
|
header = map[string]string{api.AmzACL: "private"}
|
||||||
putBucketACL(t, tc, bktName, box, header)
|
putBucketACL(tc, bktName, box, header)
|
||||||
checkLastRecords(t, tc, bktInfo, eacl.ActionDeny)
|
checkLastRecords(t, tc, bktInfo, eacl.ActionDeny)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPutBucketAPE(t *testing.T) {
|
||||||
|
hc := prepareHandlerContext(t)
|
||||||
|
bktName := "bucket-for-acl-ape"
|
||||||
|
|
||||||
|
info := createBucket(hc, bktName)
|
||||||
|
|
||||||
|
_, err := hc.tp.ContainerEACL(hc.Context(), info.BktInfo.CID)
|
||||||
|
require.ErrorContains(t, err, "not found")
|
||||||
|
|
||||||
|
chains, err := hc.h.ape.ListChains(engine.NamespaceTarget(""))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, chains, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPutBucketObjectACLErrorAPE(t *testing.T) {
|
||||||
|
hc := prepareHandlerContext(t)
|
||||||
|
bktName, objName := "bucket-for-acl-ape", "object"
|
||||||
|
|
||||||
|
info := createBucket(hc, bktName)
|
||||||
|
putObject(hc, bktName, objName)
|
||||||
|
|
||||||
|
aclBody := &AccessControlPolicy{}
|
||||||
|
putBucketACLAssertS3Error(hc, bktName, info.Box, nil, aclBody, s3errors.ErrAccessControlListNotSupported)
|
||||||
|
|
||||||
|
putObjectACLAssertS3Error(hc, bktName, objName, info.Box, nil, aclBody, s3errors.ErrAccessControlListNotSupported)
|
||||||
|
getObjectACLAssertS3Error(hc, bktName, objName, s3errors.ErrAccessControlListNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetBucketACLAPE(t *testing.T) {
|
||||||
|
hc := prepareHandlerContext(t)
|
||||||
|
bktName := "bucket-for-acl-ape"
|
||||||
|
|
||||||
|
info := createBucket(hc, bktName)
|
||||||
|
|
||||||
|
aclRes := getBucketACL(hc, bktName)
|
||||||
|
checkPrivateBucketACL(t, aclRes, info.Key.PublicKey())
|
||||||
|
|
||||||
|
putBucketACL(hc, bktName, info.Box, map[string]string{api.AmzACL: basicACLPrivate})
|
||||||
|
aclRes = getBucketACL(hc, bktName)
|
||||||
|
checkPrivateBucketACL(t, aclRes, info.Key.PublicKey())
|
||||||
|
|
||||||
|
putBucketACL(hc, bktName, info.Box, map[string]string{api.AmzACL: basicACLReadOnly})
|
||||||
|
aclRes = getBucketACL(hc, bktName)
|
||||||
|
checkPublicReadBucketACL(t, aclRes, info.Key.PublicKey())
|
||||||
|
|
||||||
|
putBucketACL(hc, bktName, info.Box, map[string]string{api.AmzACL: basicACLPublic})
|
||||||
|
aclRes = getBucketACL(hc, bktName)
|
||||||
|
checkPublicReadWriteBucketACL(t, aclRes, info.Key.PublicKey())
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkPrivateBucketACL(t *testing.T, aclRes *AccessControlPolicy, ownerKey *keys.PublicKey) {
|
||||||
|
checkBucketACLOwner(t, aclRes, ownerKey, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkPublicReadBucketACL(t *testing.T, aclRes *AccessControlPolicy, ownerKey *keys.PublicKey) {
|
||||||
|
checkBucketACLOwner(t, aclRes, ownerKey, 2)
|
||||||
|
|
||||||
|
require.Equal(t, allUsersGroup, aclRes.AccessControlList[1].Grantee.URI)
|
||||||
|
require.Equal(t, aclRead, aclRes.AccessControlList[1].Permission)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkPublicReadWriteBucketACL(t *testing.T, aclRes *AccessControlPolicy, ownerKey *keys.PublicKey) {
|
||||||
|
checkBucketACLOwner(t, aclRes, ownerKey, 3)
|
||||||
|
|
||||||
|
require.Equal(t, allUsersGroup, aclRes.AccessControlList[1].Grantee.URI)
|
||||||
|
require.Equal(t, aclWrite, aclRes.AccessControlList[1].Permission)
|
||||||
|
|
||||||
|
require.Equal(t, allUsersGroup, aclRes.AccessControlList[2].Grantee.URI)
|
||||||
|
require.Equal(t, aclRead, aclRes.AccessControlList[2].Permission)
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkBucketACLOwner(t *testing.T, aclRes *AccessControlPolicy, ownerKey *keys.PublicKey, ln int) {
|
||||||
|
ownerIDStr := hex.EncodeToString(ownerKey.Bytes())
|
||||||
|
ownerNameStr := ownerKey.Address()
|
||||||
|
|
||||||
|
require.Equal(t, ownerIDStr, aclRes.Owner.ID)
|
||||||
|
require.Equal(t, ownerNameStr, aclRes.Owner.DisplayName)
|
||||||
|
|
||||||
|
require.Len(t, aclRes.AccessControlList, ln)
|
||||||
|
|
||||||
|
require.Equal(t, ownerIDStr, aclRes.AccessControlList[0].Grantee.ID)
|
||||||
|
require.Equal(t, ownerNameStr, aclRes.AccessControlList[0].Grantee.DisplayName)
|
||||||
|
require.Equal(t, aclFullControl, aclRes.AccessControlList[0].Permission)
|
||||||
|
}
|
||||||
|
|
||||||
func TestBucketPolicy(t *testing.T) {
|
func TestBucketPolicy(t *testing.T) {
|
||||||
hc := prepareHandlerContext(t)
|
hc := prepareHandlerContext(t)
|
||||||
bktName := "bucket-for-policy"
|
bktName := "bucket-for-policy"
|
||||||
|
@ -1490,15 +1576,26 @@ func createAccessBox(t *testing.T) (*accessbox.Box, *keys.PrivateKey) {
|
||||||
return box, key
|
return box, key
|
||||||
}
|
}
|
||||||
|
|
||||||
func createBucket(hc *handlerContext, bktName string) (*data.BucketInfo, *accessbox.Box) {
|
type createBucketInfo struct {
|
||||||
box, _ := createAccessBox(hc.t)
|
BktInfo *data.BucketInfo
|
||||||
|
Box *accessbox.Box
|
||||||
|
Key *keys.PrivateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
func createBucket(hc *handlerContext, bktName string) *createBucketInfo {
|
||||||
|
box, key := createAccessBox(hc.t)
|
||||||
|
|
||||||
w := createBucketBase(hc, bktName, box)
|
w := createBucketBase(hc, bktName, box)
|
||||||
assertStatus(hc.t, w, http.StatusOK)
|
assertStatus(hc.t, w, http.StatusOK)
|
||||||
|
|
||||||
bktInfo, err := hc.Layer().GetBucketInfo(hc.Context(), bktName)
|
bktInfo, err := hc.Layer().GetBucketInfo(hc.Context(), bktName)
|
||||||
require.NoError(hc.t, err)
|
require.NoError(hc.t, err)
|
||||||
return bktInfo, box
|
|
||||||
|
return &createBucketInfo{
|
||||||
|
BktInfo: bktInfo,
|
||||||
|
Box: box,
|
||||||
|
Key: key,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createBucketOldACL(hc *handlerContext, bktName string, box *accessbox.Box) *data.BucketInfo {
|
func createBucketOldACL(hc *handlerContext, bktName string, box *accessbox.Box) *data.BucketInfo {
|
||||||
|
@ -1556,13 +1653,64 @@ func createBucketBase(hc *handlerContext, bktName string, box *accessbox.Box) *h
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
func putBucketACL(t *testing.T, tc *handlerContext, bktName string, box *accessbox.Box, header map[string]string) {
|
func putBucketACL(hc *handlerContext, bktName string, box *accessbox.Box, header map[string]string) {
|
||||||
w, r := prepareTestRequest(tc, bktName, "", nil)
|
w := putBucketACLBase(hc, bktName, box, header, nil)
|
||||||
|
assertStatus(hc.t, w, http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
func putBucketACLAssertS3Error(hc *handlerContext, bktName string, box *accessbox.Box, header map[string]string, body *AccessControlPolicy, code s3errors.ErrorCode) {
|
||||||
|
w := putBucketACLBase(hc, bktName, box, header, body)
|
||||||
|
assertS3Error(hc.t, w, s3errors.GetAPIError(code))
|
||||||
|
}
|
||||||
|
|
||||||
|
func putBucketACLBase(hc *handlerContext, bktName string, box *accessbox.Box, header map[string]string, body *AccessControlPolicy) *httptest.ResponseRecorder {
|
||||||
|
w, r := prepareTestRequest(hc, bktName, "", body)
|
||||||
for key, val := range header {
|
for key, val := range header {
|
||||||
r.Header.Set(key, val)
|
r.Header.Set(key, val)
|
||||||
}
|
}
|
||||||
ctx := middleware.SetBoxData(r.Context(), box)
|
ctx := middleware.SetBoxData(r.Context(), box)
|
||||||
r = r.WithContext(ctx)
|
r = r.WithContext(ctx)
|
||||||
tc.Handler().PutBucketACLHandler(w, r)
|
hc.Handler().PutBucketACLHandler(w, r)
|
||||||
assertStatus(t, w, http.StatusOK)
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBucketACL(hc *handlerContext, bktName string) *AccessControlPolicy {
|
||||||
|
w := getBucketACLBase(hc, bktName)
|
||||||
|
assertStatus(hc.t, w, http.StatusOK)
|
||||||
|
res := &AccessControlPolicy{}
|
||||||
|
parseTestResponse(hc.t, w, res)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func getBucketACLBase(hc *handlerContext, bktName string) *httptest.ResponseRecorder {
|
||||||
|
w, r := prepareTestRequest(hc, bktName, "", nil)
|
||||||
|
hc.Handler().GetBucketACLHandler(w, r)
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
func putObjectACLAssertS3Error(hc *handlerContext, bktName, objName string, box *accessbox.Box, header map[string]string, body *AccessControlPolicy, code s3errors.ErrorCode) {
|
||||||
|
w := putObjectACLBase(hc, bktName, objName, box, header, body)
|
||||||
|
assertS3Error(hc.t, w, s3errors.GetAPIError(code))
|
||||||
|
}
|
||||||
|
|
||||||
|
func putObjectACLBase(hc *handlerContext, bktName, objName string, box *accessbox.Box, header map[string]string, body *AccessControlPolicy) *httptest.ResponseRecorder {
|
||||||
|
w, r := prepareTestRequest(hc, bktName, objName, body)
|
||||||
|
for key, val := range header {
|
||||||
|
r.Header.Set(key, val)
|
||||||
|
}
|
||||||
|
ctx := middleware.SetBoxData(r.Context(), box)
|
||||||
|
r = r.WithContext(ctx)
|
||||||
|
hc.Handler().PutObjectACLHandler(w, r)
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
func getObjectACLAssertS3Error(hc *handlerContext, bktName, objName string, code s3errors.ErrorCode) {
|
||||||
|
w := getObjectACLBase(hc, bktName, objName)
|
||||||
|
assertS3Error(hc.t, w, s3errors.GetAPIError(code))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getObjectACLBase(hc *handlerContext, bktName, objName string) *httptest.ResponseRecorder {
|
||||||
|
w, r := prepareTestRequest(hc, bktName, objName, nil)
|
||||||
|
hc.Handler().GetObjectACLHandler(w, r)
|
||||||
|
return w
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,8 +266,8 @@ func (a *apeMock) DeletePolicy(namespace string, cnrID cid.ID) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestBucket(hc *handlerContext, bktName string) *data.BucketInfo {
|
func createTestBucket(hc *handlerContext, bktName string) *data.BucketInfo {
|
||||||
bktInfo, _ := createBucket(hc, bktName)
|
info := createBucket(hc, bktName)
|
||||||
return bktInfo
|
return info.BktInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestBucketWithLock(hc *handlerContext, bktName string, conf *data.ObjectLockConfiguration) *data.BucketInfo {
|
func createTestBucketWithLock(hc *handlerContext, bktName string, conf *data.ObjectLockConfiguration) *data.BucketInfo {
|
||||||
|
|
|
@ -372,8 +372,8 @@ func TestCreateBucket(t *testing.T) {
|
||||||
hc := prepareHandlerContext(t)
|
hc := prepareHandlerContext(t)
|
||||||
bktName := "bkt-name"
|
bktName := "bkt-name"
|
||||||
|
|
||||||
_, box := createBucket(hc, bktName)
|
info := createBucket(hc, bktName)
|
||||||
createBucketAssertS3Error(hc, bktName, box, s3errors.ErrBucketAlreadyOwnedByYou)
|
createBucketAssertS3Error(hc, bktName, info.Box, s3errors.ErrBucketAlreadyOwnedByYou)
|
||||||
|
|
||||||
box2, _ := createAccessBox(t)
|
box2, _ := createAccessBox(t)
|
||||||
createBucketAssertS3Error(hc, bktName, box2, s3errors.ErrBucketAlreadyExists)
|
createBucketAssertS3Error(hc, bktName, box2, s3errors.ErrBucketAlreadyExists)
|
||||||
|
|
|
@ -108,7 +108,7 @@ var basicACLZero acl.Basic
|
||||||
// If prm.BasicACL is zero, 'eacl-public-read-write' is used.
|
// If prm.BasicACL is zero, 'eacl-public-read-write' is used.
|
||||||
func (x *FrostFS) CreateContainer(ctx context.Context, prm layer.PrmContainerCreate) (*layer.ContainerCreateResult, error) {
|
func (x *FrostFS) CreateContainer(ctx context.Context, prm layer.PrmContainerCreate) (*layer.ContainerCreateResult, error) {
|
||||||
if prm.BasicACL == basicACLZero {
|
if prm.BasicACL == basicACLZero {
|
||||||
prm.BasicACL = acl.PublicRW
|
prm.BasicACL = acl.PublicRWExtended
|
||||||
}
|
}
|
||||||
|
|
||||||
var cnr container.Container
|
var cnr container.Container
|
||||||
|
|
Loading…
Reference in a new issue