frostfs-s3-gw/internal/frostfs/policy/morph_rule_chain_storage.go
Alex Vanin 6bf6a3b1a3
All checks were successful
/ DCO (pull_request) Successful in 4m8s
/ Vulncheck (pull_request) Successful in 4m10s
/ Builds (1.20) (pull_request) Successful in 5m33s
/ Builds (1.21) (pull_request) Successful in 5m24s
/ Lint (pull_request) Successful in 8m32s
/ Tests (1.20) (pull_request) Successful in 5m9s
/ Tests (1.21) (pull_request) Successful in 4m52s
[#362] Check user and groups during policy check
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2024-05-08 15:25:14 +03:00

134 lines
3.9 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.ContainerTarget(cnrID.EncodeToString()), Name: chain.S3})
tx := c.contract.StartTx()
tx.AddChain(policycontract.IAM, ns, getBucketPolicyName(cnrID), policy)
for i := range chains {
tx.AddChain(policycontract.Container, cnrID.EncodeToString(), 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.ContainerTarget(cnrID.EncodeToString()), Name: chain.S3})
tx := c.contract.StartTx()
for _, chainID := range chainIDs {
tx.RemoveChain(policycontract.Container, cnrID.EncodeToString(), 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(cid string, chains []*chain.Chain) error {
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.ContainerTarget(cid), Name: chain.S3})
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.ContainerTarget(cid), Name: chain.Ingress})
tx := c.contract.StartTx()
for i := range chains {
tx.AddChain(policycontract.Container, cid, chains[i].ID, chains[i].Bytes())
}
return c.contract.SendTx(tx)
}
func getKind(target engine.Target) policycontract.Kind {
switch target.Type {
case engine.Container:
return policycontract.Container
case engine.User:
return 'u'
case engine.Group:
return 'g'
default:
return policycontract.Namespace
}
}
func getBucketPolicyName(cnrID cid.ID) []byte {
return append([]byte{bucketPolicyPrefix}, cnrID[:]...)
}