From 4767eeed8c6673dfd5f85c7f4070d070c93f0514 Mon Sep 17 00:00:00 2001 From: Angira Kekteeva Date: Wed, 1 Jun 2022 21:35:20 +0400 Subject: [PATCH] [#487] Remove attach of bearer token When bucket owner is not an issuer of the bearer token Signed-off-by: Angira Kekteeva --- api/handler/get.go | 1 - api/handler/head.go | 1 - api/layer/layer.go | 14 +++---- api/layer/multipart_upload.go | 16 ++++---- api/layer/object.go | 71 +++++++++++++++++++---------------- api/layer/system_object.go | 20 ++++------ api/layer/versioning_test.go | 1 - 7 files changed, 59 insertions(+), 65 deletions(-) diff --git a/api/handler/get.go b/api/handler/get.go index 546ba374..cd7080ec 100644 --- a/api/handler/get.go +++ b/api/handler/get.go @@ -164,7 +164,6 @@ func (h *handler) GetObjectHandler(w http.ResponseWriter, r *http.Request) { ObjectInfo: info, Writer: w, Range: params, - VersionID: p.VersionID, } if err = h.obj.GetObject(r.Context(), getParams); err != nil { h.logAndSendError(w, "could not get object", reqInfo, err) diff --git a/api/handler/head.go b/api/handler/head.go index 51812b09..67c4a525 100644 --- a/api/handler/head.go +++ b/api/handler/head.go @@ -74,7 +74,6 @@ func (h *handler) HeadObjectHandler(w http.ResponseWriter, r *http.Request) { ObjectInfo: info, Writer: buffer, Range: getRangeToDetectContentType(info.Size), - VersionID: reqInfo.URL.Query().Get(api.QueryVersionID), } if err = h.obj.GetObject(r.Context(), getParams); err != nil { h.logAndSendError(w, "could not get object", reqInfo, err, zap.Stringer("oid", info.ID)) diff --git a/api/layer/layer.go b/api/layer/layer.go index a09431b7..e16e9f16 100644 --- a/api/layer/layer.go +++ b/api/layer/layer.go @@ -79,7 +79,6 @@ type ( Range *RangeParams ObjectInfo *data.ObjectInfo Writer io.Writer - VersionID string } // HeadObjectParams stores object head request parameters. @@ -323,10 +322,12 @@ func (n *layer) Owner(ctx context.Context) user.ID { return ownerID } -func (n *layer) prepareAuthParameters(ctx context.Context, prm *neofs.PrmAuth) { +func (n *layer) prepareAuthParameters(ctx context.Context, prm *neofs.PrmAuth, bktOwner user.ID) { if bd, ok := ctx.Value(api.BoxData).(*accessbox.Box); ok && bd != nil && bd.Gate != nil { - prm.BearerToken = bd.Gate.BearerToken - return + if issuer, ok := bd.Gate.BearerToken.Issuer(); ok && bktOwner.Equals(issuer) { + prm.BearerToken = bd.Gate.BearerToken + return + } } prm.PrivateKey = &n.anonKey.Key.PrivateKey @@ -380,8 +381,7 @@ func (n *layer) ListBuckets(ctx context.Context) ([]*data.BucketInfo, error) { func (n *layer) GetObject(ctx context.Context, p *GetObjectParams) error { var params getParams - params.oid = p.ObjectInfo.ID - params.cid = p.ObjectInfo.CID + params.objInfo = p.ObjectInfo if p.Range != nil { if p.Range.Start > p.Range.End { @@ -584,7 +584,7 @@ func (n *layer) deleteObject(ctx context.Context, bkt *data.BucketInfo, settings } for _, id := range ids { - if err = n.objectDelete(ctx, bkt.CID, id); err != nil { + if err = n.objectDelete(ctx, bkt, id); err != nil { obj.Error = err return obj } diff --git a/api/layer/multipart_upload.go b/api/layer/multipart_upload.go index c77990b5..1eae6577 100644 --- a/api/layer/multipart_upload.go +++ b/api/layer/multipart_upload.go @@ -209,7 +209,7 @@ func (x *multiObjectReader) Read(p []byte) (n int, err error) { return n, io.EOF } - x.prm.oid = x.parts[0].ID + x.prm.objInfo = x.parts[0] x.curReader, err = x.layer.initObjectPayloadReader(x.ctx, x.prm) if err != nil { @@ -307,8 +307,6 @@ func (n *layer) CompleteMultipartUpload(ctx context.Context, p *CompleteMultipar parts: parts, } - r.prm.cid = p.Info.Bkt.CID - obj, err = n.PutObject(ctx, &PutObjectParams{ BktInfo: p.Info.Bkt, Object: p.Info.Key, @@ -328,7 +326,7 @@ func (n *layer) CompleteMultipartUpload(ctx context.Context, p *CompleteMultipar if partNum == 0 { continue } - if err = n.objectDelete(ctx, p.Info.Bkt.CID, objInfo.ID); err != nil { + if err = n.objectDelete(ctx, p.Info.Bkt, objInfo.ID); err != nil { n.log.Warn("could not delete upload part", zap.Stringer("object id", objInfo.ID), zap.Stringer("bucket id", p.Info.Bkt.CID), @@ -348,7 +346,7 @@ func (n *layer) ListMultipartUploads(ctx context.Context, p *ListMultipartUpload f := &findParams{ attr: [2]string{UploadPartNumberAttributeName, "0"}, - cid: p.Bkt.CID, + bkt: p.Bkt, } ids, err := n.objectSearch(ctx, f) @@ -360,7 +358,7 @@ func (n *layer) ListMultipartUploads(ctx context.Context, p *ListMultipartUpload uniqDirs := make(map[string]struct{}) for i := range ids { - meta, err := n.objectHead(ctx, p.Bkt.CID, ids[i]) + meta, err := n.objectHead(ctx, p.Bkt, ids[i]) if err != nil { n.log.Warn("couldn't head object", zap.Stringer("object id", &ids[i]), @@ -420,7 +418,7 @@ func (n *layer) AbortMultipartUpload(ctx context.Context, p *UploadInfoParams) e } for _, info := range objects { - err := n.objectDelete(ctx, info.CID, info.ID) + err := n.objectDelete(ctx, p.Bkt, info.ID) if err != nil { return err } @@ -493,7 +491,7 @@ func (n *layer) getUploadParts(ctx context.Context, p *UploadInfoParams) (map[in // and search in attributes by prefix is not supported f := &findParams{ attr: [2]string{UploadIDAttributeName, p.UploadID}, - cid: p.Bkt.CID, + bkt: p.Bkt, } ids, err := n.objectSearch(ctx, f) @@ -504,7 +502,7 @@ func (n *layer) getUploadParts(ctx context.Context, p *UploadInfoParams) (map[in res := make(map[int]*data.ObjectInfo) for i := range ids { - meta, err := n.objectHead(ctx, p.Bkt.CID, ids[i]) + meta, err := n.objectHead(ctx, p.Bkt, ids[i]) if err != nil { n.log.Warn("couldn't head a part of upload", zap.Stringer("object id", &ids[i]), diff --git a/api/layer/object.go b/api/layer/object.go index 8a2da369..ab71784c 100644 --- a/api/layer/object.go +++ b/api/layer/object.go @@ -27,7 +27,7 @@ import ( type ( findParams struct { attr [2]string - cid cid.ID + bkt *data.BucketInfo prefix string } @@ -35,8 +35,7 @@ type ( // payload range off, ln uint64 - cid cid.ID - oid oid.ID + objInfo *data.ObjectInfo } // ListObjectsParamsCommon contains common parameters for ListObjectsV1 and ListObjectsV2. @@ -69,10 +68,10 @@ type ( } ) -func (n *layer) objectSearchByName(ctx context.Context, cnr cid.ID, filename string) ([]oid.ID, error) { +func (n *layer) objectSearchByName(ctx context.Context, bktInfo *data.BucketInfo, filename string) ([]oid.ID, error) { f := &findParams{ attr: [2]string{object.AttributeFileName, filename}, - cid: cnr, + bkt: bktInfo, } return n.objectSearch(ctx, f) } @@ -80,12 +79,12 @@ func (n *layer) objectSearchByName(ctx context.Context, cnr cid.ID, filename str // objectSearch returns all available objects by search params. func (n *layer) objectSearch(ctx context.Context, p *findParams) ([]oid.ID, error) { prm := neofs.PrmObjectSelect{ - Container: p.cid, + Container: p.bkt.CID, ExactAttribute: p.attr, FilePrefix: p.prefix, } - n.prepareAuthParameters(ctx, &prm.PrmAuth) + n.prepareAuthParameters(ctx, &prm.PrmAuth, p.bkt.Owner) res, err := n.neoFS.SelectObjects(ctx, prm) @@ -100,14 +99,14 @@ func newAddress(cnr cid.ID, obj oid.ID) oid.Address { } // objectHead returns all object's headers. -func (n *layer) objectHead(ctx context.Context, idCnr cid.ID, idObj oid.ID) (*object.Object, error) { +func (n *layer) objectHead(ctx context.Context, bktInfo *data.BucketInfo, idObj oid.ID) (*object.Object, error) { prm := neofs.PrmObjectRead{ - Container: idCnr, + Container: bktInfo.CID, Object: idObj, WithHeader: true, } - n.prepareAuthParameters(ctx, &prm.PrmAuth) + n.prepareAuthParameters(ctx, &prm.PrmAuth, bktInfo.Owner) res, err := n.neoFS.ReadObject(ctx, prm) if err != nil { @@ -121,13 +120,19 @@ func (n *layer) objectHead(ctx context.Context, idCnr cid.ID, idObj oid.ID) (*ob // Zero range corresponds to full payload (panics if only offset is set). func (n *layer) initObjectPayloadReader(ctx context.Context, p getParams) (io.Reader, error) { prm := neofs.PrmObjectRead{ - Container: p.cid, - Object: p.oid, + Container: p.objInfo.CID, + Object: p.objInfo.ID, WithPayload: true, PayloadRange: [2]uint64{p.off, p.ln}, } - n.prepareAuthParameters(ctx, &prm.PrmAuth) + // should be taken from cache + bktInfo, err := n.GetBucketInfo(ctx, p.objInfo.Bucket) + if err != nil { + return nil, err + } + + n.prepareAuthParameters(ctx, &prm.PrmAuth, bktInfo.Owner) res, err := n.neoFS.ReadObject(ctx, prm) if err != nil { @@ -138,15 +143,15 @@ func (n *layer) initObjectPayloadReader(ctx context.Context, p getParams) (io.Re } // objectGet returns an object with payload in the object. -func (n *layer) objectGet(ctx context.Context, addr oid.Address) (*object.Object, error) { +func (n *layer) objectGet(ctx context.Context, bktInfo *data.BucketInfo, objID oid.ID) (*object.Object, error) { prm := neofs.PrmObjectRead{ - Container: addr.Container(), - Object: addr.Object(), + Container: bktInfo.CID, + Object: objID, WithHeader: true, WithPayload: true, } - n.prepareAuthParameters(ctx, &prm.PrmAuth) + n.prepareAuthParameters(ctx, &prm.PrmAuth, bktInfo.Owner) res, err := n.neoFS.ReadObject(ctx, prm) if err != nil { @@ -198,7 +203,7 @@ func (n *layer) PutObject(ctx context.Context, p *PutObjectParams) (*data.Object } } - id, hash, err := n.objectPutAndHash(ctx, prm) + id, hash, err := n.objectPutAndHash(ctx, prm, p.BktInfo) if err != nil { return nil, err } @@ -229,7 +234,7 @@ func (n *layer) PutObject(ctx context.Context, p *PutObjectParams) (*data.Object n.listsCache.CleanCacheEntriesContainingObject(p.Object, p.BktInfo.CID) for _, id := range idsToDeleteArr { - if err = n.objectDelete(ctx, p.BktInfo.CID, id); err != nil { + if err = n.objectDelete(ctx, p.BktInfo, id); err != nil { n.log.Warn("couldn't delete object", zap.Stringer("version id", id), zap.Error(err)) @@ -356,7 +361,7 @@ func (n *layer) headLastVersionIfNotDeleted(ctx context.Context, bkt *data.Bucke } func (n *layer) headVersions(ctx context.Context, bkt *data.BucketInfo, objectName string) (*objectVersions, error) { - ids, err := n.objectSearchByName(ctx, bkt.CID, objectName) + ids, err := n.objectSearchByName(ctx, bkt, objectName) if err != nil { return nil, err } @@ -367,7 +372,7 @@ func (n *layer) headVersions(ctx context.Context, bkt *data.BucketInfo, objectNa } for i := range ids { - meta, err := n.objectHead(ctx, bkt.CID, ids[i]) + meta, err := n.objectHead(ctx, bkt, ids[i]) if err != nil { n.log.Warn("couldn't head object", zap.Stringer("object id", &ids[i]), @@ -416,7 +421,7 @@ func (n *layer) headVersion(ctx context.Context, bkt *data.BucketInfo, p *HeadOb return objInfoFromMeta(bkt, headInfo), nil } - meta, err := n.objectHead(ctx, bkt.CID, id) + meta, err := n.objectHead(ctx, bkt, id) if err != nil { if client.IsErrObjectNotFound(err) { return nil, apiErrors.GetAPIError(apiErrors.ErrNoSuchVersion) @@ -438,23 +443,23 @@ func (n *layer) headVersion(ctx context.Context, bkt *data.BucketInfo, p *HeadOb } // objectDelete puts tombstone object into neofs. -func (n *layer) objectDelete(ctx context.Context, idCnr cid.ID, idObj oid.ID) error { +func (n *layer) objectDelete(ctx context.Context, bktInfo *data.BucketInfo, idObj oid.ID) error { prm := neofs.PrmObjectDelete{ - Container: idCnr, + Container: bktInfo.CID, Object: idObj, } - n.prepareAuthParameters(ctx, &prm.PrmAuth) + n.prepareAuthParameters(ctx, &prm.PrmAuth, bktInfo.Owner) - n.objCache.Delete(newAddress(idCnr, idObj)) + n.objCache.Delete(newAddress(bktInfo.CID, idObj)) return n.transformNeofsError(ctx, n.neoFS.DeleteObject(ctx, prm)) } // objectPutAndHash prepare auth parameters and invoke neofs.CreateObject. // Returns object ID and payload sha256 hash. -func (n *layer) objectPutAndHash(ctx context.Context, prm neofs.PrmObjectCreate) (*oid.ID, []byte, error) { - n.prepareAuthParameters(ctx, &prm.PrmAuth) +func (n *layer) objectPutAndHash(ctx context.Context, prm neofs.PrmObjectCreate, bktInfo *data.BucketInfo) (*oid.ID, []byte, error) { + n.prepareAuthParameters(ctx, &prm.PrmAuth, bktInfo.Owner) hash := sha256.New() prm.Payload = wrapReader(prm.Payload, 64*1024, func(buf []byte) { hash.Write(buf) @@ -565,7 +570,7 @@ func (n *layer) getAllObjectsVersions(ctx context.Context, bkt *data.BucketInfo, ids := n.listsCache.Get(cacheKey) if ids == nil { - ids, err = n.objectSearch(ctx, &findParams{cid: bkt.CID, prefix: prefix}) + ids, err = n.objectSearch(ctx, &findParams{bkt: bkt, prefix: prefix}) if err != nil { return nil, err } @@ -577,7 +582,7 @@ func (n *layer) getAllObjectsVersions(ctx context.Context, bkt *data.BucketInfo, versions := make(map[string]*objectVersions, len(ids)/2) for i := 0; i < len(ids); i++ { - obj := n.objectFromObjectsCacheOrNeoFS(ctx, bkt.CID, ids[i]) + obj := n.objectFromObjectsCacheOrNeoFS(ctx, bkt, ids[i]) if obj == nil { continue } @@ -681,13 +686,13 @@ func (n *layer) isVersioningEnabled(ctx context.Context, bktInfo *data.BucketInf return settings.VersioningEnabled } -func (n *layer) objectFromObjectsCacheOrNeoFS(ctx context.Context, cnr cid.ID, obj oid.ID) *object.Object { +func (n *layer) objectFromObjectsCacheOrNeoFS(ctx context.Context, bktInfo *data.BucketInfo, obj oid.ID) *object.Object { var ( err error - meta = n.objCache.Get(newAddress(cnr, obj)) + meta = n.objCache.Get(newAddress(bktInfo.CID, obj)) ) if meta == nil { - meta, err = n.objectHead(ctx, cnr, obj) + meta, err = n.objectHead(ctx, bktInfo, obj) if err != nil { n.log.Warn("could not fetch object meta", zap.Error(err)) return nil diff --git a/api/layer/system_object.go b/api/layer/system_object.go index 4ed501aa..eb4e3e4e 100644 --- a/api/layer/system_object.go +++ b/api/layer/system_object.go @@ -15,7 +15,6 @@ import ( "github.com/nspcc-dev/neofs-s3-gw/api/layer/neofs" "github.com/nspcc-dev/neofs-s3-gw/internal/misc" "github.com/nspcc-dev/neofs-sdk-go/object" - oid "github.com/nspcc-dev/neofs-sdk-go/object/id" "go.uber.org/zap" ) @@ -60,7 +59,7 @@ func (n *layer) HeadSystemObject(ctx context.Context, bkt *data.BucketInfo, objN func (n *layer) DeleteSystemObject(ctx context.Context, bktInfo *data.BucketInfo, name string) error { f := &findParams{ attr: [2]string{objectSystemAttributeName, name}, - cid: bktInfo.CID, + bkt: bktInfo, } ids, err := n.objectSearch(ctx, f) if err != nil { @@ -69,7 +68,7 @@ func (n *layer) DeleteSystemObject(ctx context.Context, bktInfo *data.BucketInfo n.systemCache.Delete(systemObjectKey(bktInfo, name)) for i := range ids { - if err = n.objectDelete(ctx, bktInfo.CID, ids[i]); err != nil { + if err = n.objectDelete(ctx, bktInfo, ids[i]); err != nil { return err } } @@ -119,7 +118,7 @@ func (n *layer) putSystemObjectIntoNeoFS(ctx context.Context, p *PutSystemObject prm.Attributes = append(prm.Attributes, [2]string{k, v}) } - id, hash, err := n.objectPutAndHash(ctx, prm) + id, hash, err := n.objectPutAndHash(ctx, prm, p.BktInfo) if err != nil { return nil, err } @@ -133,7 +132,7 @@ func (n *layer) putSystemObjectIntoNeoFS(ctx context.Context, p *PutSystemObject } for _, id := range idsToDeleteArr { - if err = n.objectDelete(ctx, p.BktInfo.CID, id); err != nil { + if err = n.objectDelete(ctx, p.BktInfo, id); err != nil { n.log.Warn("couldn't delete system object", zap.Stringer("version id", id), zap.String("name", misc.SanitizeString(p.ObjName)), @@ -169,12 +168,7 @@ func (n *layer) getSystemObjectFromNeoFS(ctx context.Context, bkt *data.BucketIn objInfo := versions.getLast() - var addr oid.Address - - addr.SetContainer(bkt.CID) - addr.SetObject(objInfo.ID) - - obj, err := n.objectGet(ctx, addr) + obj, err := n.objectGet(ctx, bkt, objInfo.ID) if err != nil { return nil, err } @@ -215,7 +209,7 @@ func (n *layer) getCORS(ctx context.Context, bkt *data.BucketInfo, sysName strin func (n *layer) headSystemVersions(ctx context.Context, bkt *data.BucketInfo, sysName string) (*objectVersions, error) { f := &findParams{ attr: [2]string{objectSystemAttributeName, sysName}, - cid: bkt.CID, + bkt: bkt, } ids, err := n.objectSearch(ctx, f) if err != nil { @@ -224,7 +218,7 @@ func (n *layer) headSystemVersions(ctx context.Context, bkt *data.BucketInfo, sy versions := newObjectVersions(sysName) for i := range ids { - meta, err := n.objectHead(ctx, bkt.CID, ids[i]) + meta, err := n.objectHead(ctx, bkt, ids[i]) if err != nil { n.log.Warn("couldn't head object", zap.Stringer("object id", &ids[i]), diff --git a/api/layer/versioning_test.go b/api/layer/versioning_test.go index 1d245bac..c509790b 100644 --- a/api/layer/versioning_test.go +++ b/api/layer/versioning_test.go @@ -50,7 +50,6 @@ func (tc *testContext) getObject(objectName, versionID string, needError bool) ( err = tc.layer.GetObject(tc.ctx, &GetObjectParams{ ObjectInfo: objInfo, Writer: content, - VersionID: versionID, }) require.NoError(tc.t, err)