forked from TrueCloudLab/frostfs-s3-gw
Denis Kirillov
8669bf6b50
* Remove native policy when remove bucket policy * Allow policies that contain only s3 compatible statements (now deny rules cannot be converted to native rules) Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
130 lines
3.8 KiB
Go
130 lines
3.8 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/google/uuid"
|
|
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
|
|
"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.MorphRuleChainStorageReader = (*MorphRuleChainStorage)(nil)
|
|
|
|
const bucketPolicyPrefix = 'b'
|
|
|
|
func NewMorphRuleChainStorage(config *MorphRuleChainStorageConfig) *MorphRuleChainStorage {
|
|
return &MorphRuleChainStorage{
|
|
contract: config.Contract,
|
|
cache: config.Cache,
|
|
log: config.Log,
|
|
}
|
|
}
|
|
|
|
func (c *MorphRuleChainStorage) GetAdmin() (util.Uint160, error) {
|
|
panic("should never be called")
|
|
}
|
|
|
|
func (c *MorphRuleChainStorage) ListTargetsIterator(engine.TargetType) (uuid.UUID, result.Iterator, 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, chainIDs []chain.ID) error {
|
|
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.NamespaceTarget(ns), Name: chain.S3})
|
|
|
|
tx := c.contract.StartTx()
|
|
for _, chainID := range chainIDs {
|
|
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[:]...)
|
|
}
|