From 90eb4f0188a0c2447918fc91ec64421533efe5a6 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Thu, 6 Oct 2022 11:46:53 +0300 Subject: [PATCH] [#713] Add check access control for system caches Signed-off-by: Denis Kirillov --- api/handler/versioning.go | 8 ++--- api/layer/cache.go | 70 +++++++++++++++++++++++++++++++------- api/layer/compound.go | 14 ++++---- api/layer/container.go | 1 - api/layer/cors.go | 2 +- api/layer/notifications.go | 7 ++-- api/layer/system_object.go | 19 ++++++----- api/layer/tagging.go | 32 +++++++---------- 8 files changed, 94 insertions(+), 59 deletions(-) diff --git a/api/handler/versioning.go b/api/handler/versioning.go index 8d03480f2..6235a7bd0 100644 --- a/api/handler/versioning.go +++ b/api/handler/versioning.go @@ -8,7 +8,6 @@ import ( "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/layer" - "go.uber.org/zap" ) func (h *handler) PutBucketVersioningHandler(w http.ResponseWriter, r *http.Request) { @@ -68,11 +67,8 @@ func (h *handler) GetBucketVersioningHandler(w http.ResponseWriter, r *http.Requ settings, err := h.obj.GetBucketSettings(r.Context(), bktInfo) if err != nil { - h.log.Warn("couldn't get version settings object: default version settings will be used", - zap.String("request_id", reqInfo.RequestID), - zap.String("method", reqInfo.API), - zap.String("bucket_name", reqInfo.BucketName), - zap.Error(err)) + h.logAndSendError(w, "couldn't get version settings", reqInfo, err) + return } if err = api.EncodeToResponse(w, formVersioningConfiguration(settings)); err != nil { diff --git a/api/layer/cache.go b/api/layer/cache.go index 03cbd8339..e118aa760 100644 --- a/api/layer/cache.go +++ b/api/layer/cache.go @@ -142,64 +142,110 @@ func (c *Cache) PutList(owner user.ID, key cache.ObjectsListKey, list []*data.No } } -func (c *Cache) GetTagging(key string) map[string]string { +func (c *Cache) GetTagging(owner user.ID, key string) map[string]string { + if !c.accessCache.Get(owner, key) { + return nil + } + return c.systemCache.GetTagging(key) } -func (c *Cache) PutTagging(key string, tags map[string]string) { +func (c *Cache) PutTagging(owner user.ID, key string, tags map[string]string) { if err := c.systemCache.PutTagging(key, tags); err != nil { c.logger.Error("couldn't cache tags", zap.Error(err)) } + + if err := c.accessCache.Put(owner, key); err != nil { + c.logger.Warn("couldn't cache access control operation", zap.Error(err)) + } } func (c *Cache) DeleteTagging(key string) { c.systemCache.Delete(key) } -func (c *Cache) GetLockInfo(key string) *data.LockInfo { +func (c *Cache) GetLockInfo(owner user.ID, key string) *data.LockInfo { + if !c.accessCache.Get(owner, key) { + return nil + } + return c.systemCache.GetLockInfo(key) } -func (c *Cache) PutLockInfo(key string, lockInfo *data.LockInfo) { +func (c *Cache) PutLockInfo(owner user.ID, key string, lockInfo *data.LockInfo) { if err := c.systemCache.PutLockInfo(key, lockInfo); err != nil { c.logger.Error("couldn't cache lock info", zap.Error(err)) } + + if err := c.accessCache.Put(owner, key); err != nil { + c.logger.Warn("couldn't cache access control operation", zap.Error(err)) + } } -func (c *Cache) GetSettings(bktInfo *data.BucketInfo) *data.BucketSettings { +func (c *Cache) GetSettings(owner user.ID, bktInfo *data.BucketInfo) *data.BucketSettings { key := bktInfo.Name + bktInfo.SettingsObjectName() + + if !c.accessCache.Get(owner, key) { + return nil + } + return c.systemCache.GetSettings(key) } -func (c *Cache) PutSettings(bktInfo *data.BucketInfo, settings *data.BucketSettings) { +func (c *Cache) PutSettings(owner user.ID, bktInfo *data.BucketInfo, settings *data.BucketSettings) { key := bktInfo.Name + bktInfo.SettingsObjectName() if err := c.systemCache.PutSettings(key, settings); err != nil { c.logger.Warn("couldn't cache bucket settings", zap.String("bucket", bktInfo.Name), zap.Error(err)) } + + if err := c.accessCache.Put(owner, key); err != nil { + c.logger.Warn("couldn't cache access control operation", zap.Error(err)) + } } -func (c *Cache) GetCORS(bkt *data.BucketInfo) *data.CORSConfiguration { - return c.systemCache.GetCORS(bkt.Name + bkt.CORSObjectName()) +func (c *Cache) GetCORS(owner user.ID, bkt *data.BucketInfo) *data.CORSConfiguration { + key := bkt.Name + bkt.CORSObjectName() + + if !c.accessCache.Get(owner, key) { + return nil + } + + return c.systemCache.GetCORS(key) } -func (c *Cache) PutCORS(bkt *data.BucketInfo, settings *data.CORSConfiguration) { - if err := c.systemCache.PutCORS(bkt.Name+bkt.CORSObjectName(), settings); err != nil { +func (c *Cache) PutCORS(owner user.ID, bkt *data.BucketInfo, cors *data.CORSConfiguration) { + key := bkt.Name + bkt.CORSObjectName() + + if err := c.systemCache.PutCORS(key, cors); err != nil { c.logger.Warn("couldn't cache cors", zap.String("bucket", bkt.Name), zap.Error(err)) } + + if err := c.accessCache.Put(owner, key); err != nil { + c.logger.Warn("couldn't cache access control operation", zap.Error(err)) + } } func (c *Cache) DeleteCORS(bktInfo *data.BucketInfo) { c.systemCache.Delete(bktInfo.Name + bktInfo.CORSObjectName()) } -func (c *Cache) GetNotificationConfiguration(bktInfo *data.BucketInfo) *data.NotificationConfiguration { +func (c *Cache) GetNotificationConfiguration(owner user.ID, bktInfo *data.BucketInfo) *data.NotificationConfiguration { key := bktInfo.Name + bktInfo.NotificationConfigurationObjectName() + + if !c.accessCache.Get(owner, key) { + return nil + } + return c.systemCache.GetNotificationConfiguration(key) } -func (c *Cache) PutNotificationConfiguration(bktInfo *data.BucketInfo, configuration *data.NotificationConfiguration) { +func (c *Cache) PutNotificationConfiguration(owner user.ID, bktInfo *data.BucketInfo, configuration *data.NotificationConfiguration) { key := bktInfo.Name + bktInfo.NotificationConfigurationObjectName() if err := c.systemCache.PutNotificationConfiguration(key, configuration); err != nil { c.logger.Warn("couldn't cache notification configuration", zap.String("bucket", bktInfo.Name), zap.Error(err)) } + + if err := c.accessCache.Put(owner, key); err != nil { + c.logger.Warn("couldn't cache access control operation", zap.Error(err)) + } } diff --git a/api/layer/compound.go b/api/layer/compound.go index f438c7838..b668942c5 100644 --- a/api/layer/compound.go +++ b/api/layer/compound.go @@ -9,13 +9,11 @@ import ( ) func (n *layer) GetObjectTaggingAndLock(ctx context.Context, objVersion *ObjectVersion, nodeVersion *data.NodeVersion) (map[string]string, *data.LockInfo, error) { - var ( - err error - tags map[string]string - ) + var err error + owner := n.Owner(ctx) - tags = n.cache.GetTagging(objectTaggingCacheKey(objVersion)) - lockInfo := n.cache.GetLockInfo(lockObjectKey(objVersion)) + tags := n.cache.GetTagging(owner, objectTaggingCacheKey(objVersion)) + lockInfo := n.cache.GetLockInfo(owner, lockObjectKey(objVersion)) if tags != nil && lockInfo != nil { return tags, lockInfo, nil @@ -36,8 +34,8 @@ func (n *layer) GetObjectTaggingAndLock(ctx context.Context, objVersion *ObjectV return nil, nil, err } - n.cache.PutTagging(objectTaggingCacheKey(objVersion), tags) - n.cache.PutLockInfo(lockObjectKey(objVersion), lockInfo) + n.cache.PutTagging(owner, objectTaggingCacheKey(objVersion), tags) + n.cache.PutLockInfo(owner, lockObjectKey(objVersion), lockInfo) return tags, lockInfo, nil } diff --git a/api/layer/container.go b/api/layer/container.go index 5b632a490..f70bb48af 100644 --- a/api/layer/container.go +++ b/api/layer/container.go @@ -107,7 +107,6 @@ func (n *layer) containerList(ctx context.Context) ([]*data.BucketInfo, error) { } func (n *layer) createContainer(ctx context.Context, p *CreateBucketParams) (*data.BucketInfo, error) { - var err error ownerID := n.Owner(ctx) if p.LocationConstraint == "" { p.LocationConstraint = api.DefaultLocationConstraint // s3tests_boto3.functional.test_s3:test_bucket_get_location diff --git a/api/layer/cors.go b/api/layer/cors.go index 91fab761b..acc81aafd 100644 --- a/api/layer/cors.go +++ b/api/layer/cors.go @@ -64,7 +64,7 @@ func (n *layer) PutBucketCORS(ctx context.Context, p *PutCORSParams) error { } } - n.cache.PutCORS(p.BktInfo, cors) + n.cache.PutCORS(n.Owner(ctx), p.BktInfo, cors) return nil } diff --git a/api/layer/notifications.go b/api/layer/notifications.go index 8bb7a0440..49cc11cd4 100644 --- a/api/layer/notifications.go +++ b/api/layer/notifications.go @@ -53,13 +53,14 @@ func (n *layer) PutBucketNotificationConfiguration(ctx context.Context, p *PutBu } } - n.cache.PutNotificationConfiguration(p.BktInfo, p.Configuration) + n.cache.PutNotificationConfiguration(n.Owner(ctx), p.BktInfo, p.Configuration) return nil } func (n *layer) GetBucketNotificationConfiguration(ctx context.Context, bktInfo *data.BucketInfo) (*data.NotificationConfiguration, error) { - if conf := n.cache.GetNotificationConfiguration(bktInfo); conf != nil { + owner := n.Owner(ctx) + if conf := n.cache.GetNotificationConfiguration(owner, bktInfo); conf != nil { return conf, nil } @@ -82,7 +83,7 @@ func (n *layer) GetBucketNotificationConfiguration(ctx context.Context, bktInfo } } - n.cache.PutNotificationConfiguration(bktInfo, conf) + n.cache.PutNotificationConfiguration(owner, bktInfo, conf) return conf, nil } diff --git a/api/layer/system_object.go b/api/layer/system_object.go index 5c20265eb..a19aef8d2 100644 --- a/api/layer/system_object.go +++ b/api/layer/system_object.go @@ -100,7 +100,7 @@ func (n *layer) PutLockInfo(ctx context.Context, p *PutLockInfoParams) (err erro return fmt.Errorf("couldn't put lock into tree: %w", err) } - n.cache.PutLockInfo(lockObjectKey(p.ObjVersion), lockInfo) + n.cache.PutLockInfo(n.Owner(ctx), lockObjectKey(p.ObjVersion), lockInfo) return nil } @@ -124,7 +124,8 @@ func (n *layer) putLockObject(ctx context.Context, bktInfo *data.BucketInfo, obj } func (n *layer) GetLockInfo(ctx context.Context, objVersion *ObjectVersion) (*data.LockInfo, error) { - if lockInfo := n.cache.GetLockInfo(lockObjectKey(objVersion)); lockInfo != nil { + owner := n.Owner(ctx) + if lockInfo := n.cache.GetLockInfo(owner, lockObjectKey(objVersion)); lockInfo != nil { return lockInfo, nil } @@ -141,13 +142,14 @@ func (n *layer) GetLockInfo(ctx context.Context, objVersion *ObjectVersion) (*da lockInfo = &data.LockInfo{} } - n.cache.PutLockInfo(lockObjectKey(objVersion), lockInfo) + n.cache.PutLockInfo(owner, lockObjectKey(objVersion), lockInfo) return lockInfo, nil } func (n *layer) getCORS(ctx context.Context, bkt *data.BucketInfo) (*data.CORSConfiguration, error) { - if cors := n.cache.GetCORS(bkt); cors != nil { + owner := n.Owner(ctx) + if cors := n.cache.GetCORS(owner, bkt); cors != nil { return cors, nil } @@ -172,7 +174,7 @@ func (n *layer) getCORS(ctx context.Context, bkt *data.BucketInfo) (*data.CORSCo return nil, fmt.Errorf("unmarshal cors: %w", err) } - n.cache.PutCORS(bkt, cors) + n.cache.PutCORS(owner, bkt, cors) return cors, nil } @@ -183,7 +185,8 @@ func lockObjectKey(objVersion *ObjectVersion) string { } func (n *layer) GetBucketSettings(ctx context.Context, bktInfo *data.BucketInfo) (*data.BucketSettings, error) { - if settings := n.cache.GetSettings(bktInfo); settings != nil { + owner := n.Owner(ctx) + if settings := n.cache.GetSettings(owner, bktInfo); settings != nil { return settings, nil } @@ -195,7 +198,7 @@ func (n *layer) GetBucketSettings(ctx context.Context, bktInfo *data.BucketInfo) settings = &data.BucketSettings{Versioning: data.VersioningUnversioned} } - n.cache.PutSettings(bktInfo, settings) + n.cache.PutSettings(owner, bktInfo, settings) return settings, nil } @@ -205,7 +208,7 @@ func (n *layer) PutBucketSettings(ctx context.Context, p *PutSettingsParams) err return fmt.Errorf("failed to get settings node: %w", err) } - n.cache.PutSettings(p.BktInfo, p.Settings) + n.cache.PutSettings(n.Owner(ctx), p.BktInfo, p.Settings) return nil } diff --git a/api/layer/tagging.go b/api/layer/tagging.go index bf48f6bc0..657556306 100644 --- a/api/layer/tagging.go +++ b/api/layer/tagging.go @@ -12,14 +12,10 @@ import ( ) func (n *layer) GetObjectTagging(ctx context.Context, p *ObjectVersion) (string, map[string]string, error) { - var ( - err error - tags map[string]string - ) + owner := n.Owner(ctx) if len(p.VersionID) != 0 && p.VersionID != data.UnversionedObjectVersionID { - tags = n.cache.GetTagging(objectTaggingCacheKey(p)) - if tags != nil { + if tags := n.cache.GetTagging(owner, objectTaggingCacheKey(p)); tags != nil { return p.VersionID, tags, nil } } @@ -30,12 +26,11 @@ func (n *layer) GetObjectTagging(ctx context.Context, p *ObjectVersion) (string, } p.VersionID = version.OID.EncodeToString() - tags = n.cache.GetTagging(objectTaggingCacheKey(p)) - if tags != nil { + if tags := n.cache.GetTagging(owner, objectTaggingCacheKey(p)); tags != nil { return p.VersionID, tags, nil } - tags, err = n.treeService.GetObjectTagging(ctx, p.BktInfo, version) + tags, err := n.treeService.GetObjectTagging(ctx, p.BktInfo, version) if err != nil { if errorsStd.Is(err, ErrNodeNotFound) { return "", nil, errors.GetAPIError(errors.ErrNoSuchKey) @@ -43,7 +38,7 @@ func (n *layer) GetObjectTagging(ctx context.Context, p *ObjectVersion) (string, return "", nil, err } - n.cache.PutTagging(objectTaggingCacheKey(p), tags) + n.cache.PutTagging(owner, objectTaggingCacheKey(p), tags) return p.VersionID, tags, nil } @@ -63,7 +58,7 @@ func (n *layer) PutObjectTagging(ctx context.Context, p *ObjectVersion, tagSet m return nil, err } - n.cache.PutTagging(objectTaggingCacheKey(p), tagSet) + n.cache.PutTagging(n.Owner(ctx), objectTaggingCacheKey(p), tagSet) return version, nil } @@ -90,21 +85,18 @@ func (n *layer) DeleteObjectTagging(ctx context.Context, p *ObjectVersion) (*dat } func (n *layer) GetBucketTagging(ctx context.Context, bktInfo *data.BucketInfo) (map[string]string, error) { - var ( - err error - tags map[string]string - ) + owner := n.Owner(ctx) - tags = n.cache.GetTagging(bucketTaggingCacheKey(bktInfo.CID)) - if tags != nil { + if tags := n.cache.GetTagging(owner, bucketTaggingCacheKey(bktInfo.CID)); tags != nil { return tags, nil } - if tags, err = n.treeService.GetBucketTagging(ctx, bktInfo); err != nil && !errorsStd.Is(err, ErrNodeNotFound) { + tags, err := n.treeService.GetBucketTagging(ctx, bktInfo) + if err != nil && !errorsStd.Is(err, ErrNodeNotFound) { return nil, err } - n.cache.PutTagging(bucketTaggingCacheKey(bktInfo.CID), tags) + n.cache.PutTagging(owner, bucketTaggingCacheKey(bktInfo.CID), tags) return tags, nil } @@ -114,7 +106,7 @@ func (n *layer) PutBucketTagging(ctx context.Context, bktInfo *data.BucketInfo, return err } - n.cache.PutTagging(bucketTaggingCacheKey(bktInfo.CID), tagSet) + n.cache.PutTagging(n.Owner(ctx), bucketTaggingCacheKey(bktInfo.CID), tagSet) return nil }