forked from TrueCloudLab/frostfs-s3-gw
[#347] Add setEACL session token checks
Signed-off-by: Angira Kekteeva <kira@nspcc.ru>
This commit is contained in:
parent
f274747e83
commit
a0a04a73bd
4 changed files with 127 additions and 45 deletions
|
@ -20,6 +20,7 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -168,6 +169,12 @@ func (h *handler) PutBucketACLHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
token, err := getSessionTokenSetEACL(r.Context())
|
||||||
|
if err != nil {
|
||||||
|
h.logAndSendError(w, "couldn't get eacl token", reqInfo, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
list := &AccessControlPolicy{}
|
list := &AccessControlPolicy{}
|
||||||
if r.ContentLength == 0 {
|
if r.ContentLength == 0 {
|
||||||
list, err = parseACLHeaders(r.Header, key)
|
list, err = parseACLHeaders(r.Header, key)
|
||||||
|
@ -193,14 +200,14 @@ func (h *handler) PutBucketACLHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = h.updateBucketACL(r, astBucket, bktInfo); err != nil {
|
if err = h.updateBucketACL(r, astBucket, bktInfo, token); err != nil {
|
||||||
h.logAndSendError(w, "could not update bucket acl", reqInfo, err)
|
h.logAndSendError(w, "could not update bucket acl", reqInfo, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) updateBucketACL(r *http.Request, astChild *ast, bktInfo *data.BucketInfo) error {
|
func (h *handler) updateBucketACL(r *http.Request, astChild *ast, bktInfo *data.BucketInfo, sessionToken *session.Token) error {
|
||||||
bucketACL, err := h.obj.GetBucketACL(r.Context(), bktInfo)
|
bucketACL, err := h.obj.GetBucketACL(r.Context(), bktInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not get bucket eacl: %w", err)
|
return fmt.Errorf("could not get bucket eacl: %w", err)
|
||||||
|
@ -223,6 +230,8 @@ func (h *handler) updateBucketACL(r *http.Request, astChild *ast, bktInfo *data.
|
||||||
return fmt.Errorf("could not translate ast to table: %w", err)
|
return fmt.Errorf("could not translate ast to table: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.SetSessionToken(sessionToken)
|
||||||
|
|
||||||
p := &layer.PutBucketACLParams{
|
p := &layer.PutBucketACLParams{
|
||||||
BktInfo: bktInfo,
|
BktInfo: bktInfo,
|
||||||
EACL: table,
|
EACL: table,
|
||||||
|
@ -264,6 +273,12 @@ func (h *handler) PutObjectACLHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
token, err := getSessionTokenSetEACL(r.Context())
|
||||||
|
if err != nil {
|
||||||
|
h.logAndSendError(w, "couldn't get eacl token", reqInfo, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
list := &AccessControlPolicy{}
|
list := &AccessControlPolicy{}
|
||||||
if r.ContentLength == 0 {
|
if r.ContentLength == 0 {
|
||||||
list, err = parseACLHeaders(r.Header, key)
|
list, err = parseACLHeaders(r.Header, key)
|
||||||
|
@ -305,7 +320,7 @@ func (h *handler) PutObjectACLHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = h.updateBucketACL(r, astObject, bktInfo); err != nil {
|
if err = h.updateBucketACL(r, astObject, bktInfo, token); err != nil {
|
||||||
h.logAndSendError(w, "could not update bucket acl", reqInfo, err)
|
h.logAndSendError(w, "could not update bucket acl", reqInfo, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -359,6 +374,12 @@ func (h *handler) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Request)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
token, err := getSessionTokenSetEACL(r.Context())
|
||||||
|
if err == nil {
|
||||||
|
h.logAndSendError(w, "couldn't get eacl token", reqInfo, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
bktPolicy := &bucketPolicy{Bucket: reqInfo.BucketName}
|
bktPolicy := &bucketPolicy{Bucket: reqInfo.BucketName}
|
||||||
if err := json.NewDecoder(r.Body).Decode(bktPolicy); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(bktPolicy); err != nil {
|
||||||
h.logAndSendError(w, "could not parse bucket policy", reqInfo, err)
|
h.logAndSendError(w, "could not parse bucket policy", reqInfo, err)
|
||||||
|
@ -371,7 +392,7 @@ func (h *handler) PutBucketPolicyHandler(w http.ResponseWriter, r *http.Request)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = h.updateBucketACL(r, astPolicy, bktInfo); err != nil {
|
if err = h.updateBucketACL(r, astPolicy, bktInfo, token); err != nil {
|
||||||
h.logAndSendError(w, "could not update bucket acl", reqInfo, err)
|
h.logAndSendError(w, "could not update bucket acl", reqInfo, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/data"
|
"github.com/nspcc-dev/neofs-s3-gw/api/data"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
|
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -345,6 +346,8 @@ func (h *handler) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http.
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
sessionTokenSetEACL *session.Token
|
||||||
|
|
||||||
uploadID = r.URL.Query().Get(uploadIDHeaderName)
|
uploadID = r.URL.Query().Get(uploadIDHeaderName)
|
||||||
uploadInfo = &layer.UploadInfoParams{
|
uploadInfo = &layer.UploadInfoParams{
|
||||||
UploadID: uploadID,
|
UploadID: uploadID,
|
||||||
|
@ -352,6 +355,7 @@ func (h *handler) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http.
|
||||||
Key: reqInfo.ObjectName,
|
Key: reqInfo.ObjectName,
|
||||||
}
|
}
|
||||||
additional = []zap.Field{zap.String("uploadID", uploadID), zap.String("Key", reqInfo.ObjectName)}
|
additional = []zap.Field{zap.String("uploadID", uploadID), zap.String("Key", reqInfo.ObjectName)}
|
||||||
|
uploadData = &UploadData{}
|
||||||
)
|
)
|
||||||
|
|
||||||
reqBody := new(CompleteMultipartUpload)
|
reqBody := new(CompleteMultipartUpload)
|
||||||
|
@ -371,16 +375,6 @@ func (h *handler) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &layer.CompleteMultipartParams{
|
|
||||||
Info: uploadInfo,
|
|
||||||
Parts: reqBody.Parts,
|
|
||||||
}
|
|
||||||
objInfo, err := h.obj.CompleteMultipartUpload(r.Context(), c)
|
|
||||||
if err != nil {
|
|
||||||
h.logAndSendError(w, "could not complete multipart upload", reqInfo, err, additional...)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if initPart.Size > 0 {
|
if initPart.Size > 0 {
|
||||||
initPartPayload := bytes.NewBuffer(make([]byte, 0, initPart.Size))
|
initPartPayload := bytes.NewBuffer(make([]byte, 0, initPart.Size))
|
||||||
p := &layer.GetObjectParams{
|
p := &layer.GetObjectParams{
|
||||||
|
@ -392,37 +386,53 @@ func (h *handler) CompleteMultipartUploadHandler(w http.ResponseWriter, r *http.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadData := &UploadData{}
|
|
||||||
if err = json.Unmarshal(initPartPayload.Bytes(), uploadData); err != nil {
|
if err = json.Unmarshal(initPartPayload.Bytes(), uploadData); err != nil {
|
||||||
h.logAndSendError(w, "could not unmarshal multipart upload acl and/or tagging", reqInfo, err, additional...)
|
h.logAndSendError(w, "could not unmarshal multipart upload acl and/or tagging", reqInfo, err, additional...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(uploadData.TagSet) != 0 {
|
if uploadData.ACL != nil {
|
||||||
t := &layer.PutTaggingParams{
|
if sessionTokenSetEACL, err = getSessionTokenSetEACL(r.Context()); err != nil {
|
||||||
ObjectInfo: objInfo,
|
h.logAndSendError(w, "couldn't get eacl token", reqInfo, err)
|
||||||
TagSet: uploadData.TagSet,
|
|
||||||
}
|
|
||||||
if err = h.obj.PutObjectTagging(r.Context(), t); err != nil {
|
|
||||||
h.logAndSendError(w, "could not put tagging file of completed multipart upload", reqInfo, err, additional...)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if uploadData.ACL != nil {
|
c := &layer.CompleteMultipartParams{
|
||||||
resInfo := &resourceInfo{
|
Info: uploadInfo,
|
||||||
Bucket: objInfo.Bucket,
|
Parts: reqBody.Parts,
|
||||||
Object: objInfo.Name,
|
}
|
||||||
}
|
objInfo, err := h.obj.CompleteMultipartUpload(r.Context(), c)
|
||||||
astObject, err := aclToAst(uploadData.ACL, resInfo)
|
if err != nil {
|
||||||
if err != nil {
|
h.logAndSendError(w, "could not complete multipart upload", reqInfo, err, additional...)
|
||||||
h.logAndSendError(w, "could not translate acl of completed multipart upload to ast", reqInfo, err, additional...)
|
return
|
||||||
return
|
}
|
||||||
}
|
|
||||||
if err = h.updateBucketACL(r, astObject, bktInfo); err != nil {
|
if len(uploadData.TagSet) != 0 {
|
||||||
h.logAndSendError(w, "could not update bucket acl while completing multipart upload", reqInfo, err, additional...)
|
t := &layer.PutTaggingParams{
|
||||||
return
|
ObjectInfo: objInfo,
|
||||||
}
|
TagSet: uploadData.TagSet,
|
||||||
|
}
|
||||||
|
if err = h.obj.PutObjectTagging(r.Context(), t); err != nil {
|
||||||
|
h.logAndSendError(w, "could not put tagging file of completed multipart upload", reqInfo, err, additional...)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if uploadData.ACL != nil {
|
||||||
|
resInfo := &resourceInfo{
|
||||||
|
Bucket: objInfo.Bucket,
|
||||||
|
Object: objInfo.Name,
|
||||||
|
}
|
||||||
|
astObject, err := aclToAst(uploadData.ACL, resInfo)
|
||||||
|
if err != nil {
|
||||||
|
h.logAndSendError(w, "could not translate acl of completed multipart upload to ast", reqInfo, err, additional...)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = h.updateBucketACL(r, astObject, bktInfo, sessionTokenSetEACL); err != nil {
|
||||||
|
h.logAndSendError(w, "could not update bucket acl while completing multipart upload", reqInfo, err, additional...)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/creds/accessbox"
|
"github.com/nspcc-dev/neofs-s3-gw/creds/accessbox"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -172,8 +173,21 @@ type createBucketParams struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
var newEaclTable *eacl.Table
|
var (
|
||||||
reqInfo := api.GetReqInfo(r.Context())
|
err error
|
||||||
|
newEaclTable *eacl.Table
|
||||||
|
sessionTokenEACL *session.Token
|
||||||
|
containsACL = containsACLHeaders(r)
|
||||||
|
reqInfo = api.GetReqInfo(r.Context())
|
||||||
|
)
|
||||||
|
|
||||||
|
if containsACL {
|
||||||
|
if sessionTokenEACL, err = getSessionTokenSetEACL(r.Context()); err != nil {
|
||||||
|
h.logAndSendError(w, "could not get eacl session token from a box", reqInfo, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tagSet, err := parseTaggingHeader(r.Header)
|
tagSet, err := parseTaggingHeader(r.Header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.logAndSendError(w, "could not parse tagging header", reqInfo, err)
|
h.logAndSendError(w, "could not parse tagging header", reqInfo, err)
|
||||||
|
@ -233,11 +247,12 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
h.log.Error("couldn't send notification: %w", zap.Error(err))
|
h.log.Error("couldn't send notification: %w", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if containsACLHeaders(r) {
|
if containsACL {
|
||||||
if newEaclTable, err = h.getNewEAclTable(r, bktInfo, info); err != nil {
|
if newEaclTable, err = h.getNewEAclTable(r, bktInfo, info); err != nil {
|
||||||
h.logAndSendError(w, "could not get new eacl table", reqInfo, err)
|
h.logAndSendError(w, "could not get new eacl table", reqInfo, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
newEaclTable.SetSessionToken(sessionTokenEACL)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tagSet != nil {
|
if tagSet != nil {
|
||||||
|
@ -269,10 +284,12 @@ func (h *handler) PutObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
|
func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
newEaclTable *eacl.Table
|
newEaclTable *eacl.Table
|
||||||
tagSet map[string]string
|
tagSet map[string]string
|
||||||
reqInfo = api.GetReqInfo(r.Context())
|
sessionTokenEACL *session.Token
|
||||||
metadata = make(map[string]string)
|
reqInfo = api.GetReqInfo(r.Context())
|
||||||
|
metadata = make(map[string]string)
|
||||||
|
containsACL = containsACLHeaders(r)
|
||||||
)
|
)
|
||||||
|
|
||||||
policy, err := checkPostPolicy(r, reqInfo, metadata)
|
policy, err := checkPostPolicy(r, reqInfo, metadata)
|
||||||
|
@ -290,6 +307,13 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if containsACL {
|
||||||
|
if sessionTokenEACL, err = getSessionTokenSetEACL(r.Context()); err != nil {
|
||||||
|
h.logAndSendError(w, "could not get eacl session token from a box", reqInfo, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var contentReader io.Reader
|
var contentReader io.Reader
|
||||||
var size int64
|
var size int64
|
||||||
if content, ok := r.MultipartForm.Value["file"]; ok {
|
if content, ok := r.MultipartForm.Value["file"]; ok {
|
||||||
|
@ -360,6 +384,8 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if newEaclTable != nil {
|
if newEaclTable != nil {
|
||||||
|
newEaclTable.SetSessionToken(sessionTokenEACL)
|
||||||
|
|
||||||
p := &layer.PutBucketACLParams{
|
p := &layer.PutBucketACLParams{
|
||||||
BktInfo: bktInfo,
|
BktInfo: bktInfo,
|
||||||
EACL: newEaclTable,
|
EACL: newEaclTable,
|
||||||
|
@ -582,6 +608,17 @@ func (h *handler) CreateBucketHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
policies = boxData.Policies
|
policies = boxData.Policies
|
||||||
p.SessionToken = boxData.Gate.SessionTokenForPut()
|
p.SessionToken = boxData.Gate.SessionTokenForPut()
|
||||||
|
p.EACL.SetSessionToken(boxData.Gate.SessionTokenForSetEACL())
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.SessionToken == nil {
|
||||||
|
h.logAndSendError(w, "couldn't find session token for put", reqInfo, errors.GetAPIError(errors.ErrAccessDenied))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.EACL.SessionToken() == nil {
|
||||||
|
h.logAndSendError(w, "couldn't find session token for setEACL", reqInfo, errors.GetAPIError(errors.ErrAccessDenied))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if createParams.LocationConstraint != "" {
|
if createParams.LocationConstraint != "" {
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/data"
|
|
||||||
|
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api"
|
"github.com/nspcc-dev/neofs-s3-gw/api"
|
||||||
|
"github.com/nspcc-dev/neofs-s3-gw/api/data"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
|
"github.com/nspcc-dev/neofs-s3-gw/api/errors"
|
||||||
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
"github.com/nspcc-dev/neofs-s3-gw/api/layer"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -80,3 +81,16 @@ func parseRange(s string) (*layer.RangeParams, error) {
|
||||||
End: values[1],
|
End: values[1],
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getSessionTokenSetEACL(ctx context.Context) (*session.Token, error) {
|
||||||
|
boxData, err := layer.GetBoxData(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sessionToken := boxData.Gate.SessionTokenForSetEACL()
|
||||||
|
if sessionToken == nil {
|
||||||
|
return nil, errors.GetAPIError(errors.ErrAccessDenied)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sessionToken, nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue