[#347] Add setEACL session token checks

Signed-off-by: Angira Kekteeva <kira@nspcc.ru>
This commit is contained in:
Angira Kekteeva 2022-04-18 19:35:25 +04:00 committed by Kirillov Denis
parent f274747e83
commit a0a04a73bd
4 changed files with 127 additions and 45 deletions

View file

@ -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
} }

View file

@ -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
} }
} }

View file

@ -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 != "" {

View file

@ -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
}