frostfs-s3-gw/internal/frostfs/policy/morph_rule_chain_storage.go
Denis Kirillov 8f89f275bd [#306] Save bucket policy as native chain
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2024-02-28 17:50:08 +03:00

126 lines
3.7 KiB
Go

package policy
import (
"fmt"
policycontract "git.frostfs.info/TrueCloudLab/frostfs-contract/policy"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/cache"
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
"github.com/nspcc-dev/neo-go/pkg/util"
"go.uber.org/zap"
)
type MorphRuleChainStorage struct {
contract Contract
cache *cache.MorphPolicyCache
log *zap.Logger
}
type MorphRuleChainStorageConfig struct {
Contract Contract
Cache *cache.MorphPolicyCache
Log *zap.Logger
}
var _ engine.MorphRuleChainStorage = (*MorphRuleChainStorage)(nil)
const bucketPolicyPrefix = 'b'
func NewMorphRuleChainStorage(config *MorphRuleChainStorageConfig) *MorphRuleChainStorage {
return &MorphRuleChainStorage{
contract: config.Contract,
cache: config.Cache,
log: config.Log,
}
}
func (c *MorphRuleChainStorage) AddMorphRuleChain(chain.Name, engine.Target, *chain.Chain) (util.Uint256, uint32, error) {
panic("should never be called")
}
func (c *MorphRuleChainStorage) RemoveMorphRuleChain(chain.Name, engine.Target, chain.ID) (util.Uint256, uint32, error) {
panic("should never be called")
}
func (c *MorphRuleChainStorage) ListMorphRuleChains(name chain.Name, target engine.Target) ([]*chain.Chain, error) {
key := cache.MorphPolicyCacheKey{Target: target, Name: name}
list := c.cache.Get(key)
if list != nil {
return list, nil
}
listChains, err := c.contract.ListChains(getKind(target), target.Name, []byte(name))
if err != nil {
return nil, err
}
list = make([]*chain.Chain, len(listChains))
for i, listChain := range listChains {
var item chain.Chain
if err = item.DecodeBytes(listChain); err != nil {
return nil, fmt.Errorf("unmarshal chain: %w", err)
}
list[i] = &item
}
if err = c.cache.Put(key, list); err != nil {
c.log.Warn(logs.CouldntCacheListPolicyChains)
}
return list, nil
}
func (c *MorphRuleChainStorage) PutBucketPolicy(ns string, cnrID cid.ID, policy []byte, chains []*chain.Chain) error {
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.NamespaceTarget(ns), Name: chain.S3})
tx := c.contract.StartTx()
tx.AddChain(policycontract.IAM, ns, getBucketPolicyName(cnrID), policy)
for i := range chains {
tx.AddChain(policycontract.Namespace, ns, chains[i].ID, chains[i].Bytes())
}
return c.contract.SendTx(tx)
}
func (c *MorphRuleChainStorage) DeleteBucketPolicy(ns string, cnrID cid.ID, chainID chain.ID) error {
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.NamespaceTarget(ns), Name: chain.S3})
tx := c.contract.StartTx()
tx.RemoveChain(policycontract.Namespace, ns, chainID)
tx.RemoveChain(policycontract.IAM, ns, getBucketPolicyName(cnrID))
return c.contract.SendTx(tx)
}
func (c *MorphRuleChainStorage) GetBucketPolicy(ns string, cnrID cid.ID) ([]byte, error) {
return c.contract.GetChain(policycontract.IAM, ns, getBucketPolicyName(cnrID))
}
func (c *MorphRuleChainStorage) SaveACLChains(ns string, chains []*chain.Chain) error {
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.NamespaceTarget(ns), Name: chain.S3})
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.NamespaceTarget(ns), Name: chain.Ingress})
tx := c.contract.StartTx()
for i := range chains {
tx.AddChain(policycontract.Namespace, ns, chains[i].ID, chains[i].Bytes())
}
return c.contract.SendTx(tx)
}
func getKind(target engine.Target) policycontract.Kind {
var kind policycontract.Kind = policycontract.Container
if target.Type != engine.Container {
kind = policycontract.Namespace
}
return kind
}
func getBucketPolicyName(cnrID cid.ID) []byte {
return append([]byte{bucketPolicyPrefix}, cnrID[:]...)
}