forked from TrueCloudLab/frostfs-s3-gw
[#360] Use 'c' prefix for bucket policies instead of 'n'
With 'c' prefix, acl chains become shorter, thus gateway receives shorter results and avoids sessions to neo-go. There is still issue with many IAM rules. Signed-off-by: Alex Vanin <a.vanin@yadro.com>
This commit is contained in:
parent
0cc6b41b2d
commit
b7e15402a1
8 changed files with 49 additions and 43 deletions
|
@ -450,7 +450,7 @@ func (h *handler) putBucketACLAPEHandler(w http.ResponseWriter, r *http.Request,
|
||||||
}
|
}
|
||||||
|
|
||||||
chainRules := bucketCannedACLToAPERules(cannedACL, reqInfo, key, bktInfo.CID)
|
chainRules := bucketCannedACLToAPERules(cannedACL, reqInfo, key, bktInfo.CID)
|
||||||
if err = h.ape.SaveACLChains(reqInfo.Namespace, chainRules); err != nil {
|
if err = h.ape.SaveACLChains(bktInfo.CID.EncodeToString(), chainRules); err != nil {
|
||||||
h.logAndSendError(w, "failed to add morph rule chains", reqInfo, err)
|
h.logAndSendError(w, "failed to add morph rule chains", reqInfo, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1324,7 +1324,7 @@ func TestPutBucketAPE(t *testing.T) {
|
||||||
_, err := hc.tp.ContainerEACL(hc.Context(), layer.PrmContainerEACL{ContainerID: info.BktInfo.CID})
|
_, err := hc.tp.ContainerEACL(hc.Context(), layer.PrmContainerEACL{ContainerID: info.BktInfo.CID})
|
||||||
require.ErrorContains(t, err, "not found")
|
require.ErrorContains(t, err, "not found")
|
||||||
|
|
||||||
chains, err := hc.h.ape.(*apeMock).ListChains(engine.NamespaceTarget(""))
|
chains, err := hc.h.ape.(*apeMock).ListChains(engine.ContainerTarget(info.BktInfo.CID.EncodeToString()))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, chains, 2)
|
require.Len(t, chains, 2)
|
||||||
}
|
}
|
||||||
|
@ -1472,7 +1472,7 @@ func TestDeleteBucketWithPolicy(t *testing.T) {
|
||||||
hc := prepareHandlerContext(t)
|
hc := prepareHandlerContext(t)
|
||||||
|
|
||||||
bktName := "bucket-for-policy"
|
bktName := "bucket-for-policy"
|
||||||
createTestBucket(hc, bktName)
|
bi := createTestBucket(hc, bktName)
|
||||||
|
|
||||||
newPolicy := engineiam.Policy{
|
newPolicy := engineiam.Policy{
|
||||||
Version: "2012-10-17",
|
Version: "2012-10-17",
|
||||||
|
@ -1487,12 +1487,12 @@ func TestDeleteBucketWithPolicy(t *testing.T) {
|
||||||
putBucketPolicy(hc, bktName, newPolicy)
|
putBucketPolicy(hc, bktName, newPolicy)
|
||||||
|
|
||||||
require.Len(t, hc.h.ape.(*apeMock).policyMap, 1)
|
require.Len(t, hc.h.ape.(*apeMock).policyMap, 1)
|
||||||
require.Len(t, hc.h.ape.(*apeMock).chainMap[engine.NamespaceTarget("")], 4)
|
require.Len(t, hc.h.ape.(*apeMock).chainMap[engine.ContainerTarget(bi.CID.EncodeToString())], 4)
|
||||||
|
|
||||||
deleteBucket(t, hc, bktName, http.StatusNoContent)
|
deleteBucket(t, hc, bktName, http.StatusNoContent)
|
||||||
|
|
||||||
require.Empty(t, hc.h.ape.(*apeMock).policyMap)
|
require.Empty(t, hc.h.ape.(*apeMock).policyMap)
|
||||||
chains, err := hc.h.ape.(*apeMock).ListChains(engine.NamespaceTarget(""))
|
chains, err := hc.h.ape.(*apeMock).ListChains(engine.ContainerTarget(bi.CID.EncodeToString()))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Empty(t, chains)
|
require.Empty(t, chains)
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ type (
|
||||||
PutBucketPolicy(ns string, cnrID cid.ID, policy []byte, chains []*chain.Chain) error
|
PutBucketPolicy(ns string, cnrID cid.ID, policy []byte, chains []*chain.Chain) error
|
||||||
DeleteBucketPolicy(ns string, cnrID cid.ID, chainIDs []chain.ID) error
|
DeleteBucketPolicy(ns string, cnrID cid.ID, chainIDs []chain.ID) error
|
||||||
GetBucketPolicy(ns string, cnrID cid.ID) ([]byte, error)
|
GetBucketPolicy(ns string, cnrID cid.ID) ([]byte, error)
|
||||||
SaveACLChains(ns string, chains []*chain.Chain) error
|
SaveACLChains(cid string, chains []*chain.Chain) error
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -267,7 +267,7 @@ func (a *apeMock) PutBucketPolicy(ns string, cnrID cid.ID, policy []byte, chain
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range chain {
|
for i := range chain {
|
||||||
if err := a.AddChain(engine.NamespaceTarget(ns), chain[i]); err != nil {
|
if err := a.AddChain(engine.ContainerTarget(cnrID.EncodeToString()), chain[i]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,7 +280,7 @@ func (a *apeMock) DeleteBucketPolicy(ns string, cnrID cid.ID, chainIDs []chain.I
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for i := range chainIDs {
|
for i := range chainIDs {
|
||||||
if err := a.RemoveChain(engine.NamespaceTarget(ns), chainIDs[i]); err != nil {
|
if err := a.RemoveChain(engine.ContainerTarget(cnrID.EncodeToString()), chainIDs[i]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,9 +297,9 @@ func (a *apeMock) GetBucketPolicy(ns string, cnrID cid.ID) ([]byte, error) {
|
||||||
return policy, nil
|
return policy, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *apeMock) SaveACLChains(ns string, chains []*chain.Chain) error {
|
func (a *apeMock) SaveACLChains(cid string, chains []*chain.Chain) error {
|
||||||
for i := range chains {
|
for i := range chains {
|
||||||
if err := a.AddChain(engine.NamespaceTarget(ns), chains[i]); err != nil {
|
if err := a.AddChain(engine.ContainerTarget(cid), chains[i]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -898,7 +898,7 @@ func (h *handler) createBucketHandlerPolicy(w http.ResponseWriter, r *http.Reque
|
||||||
h.reqLogger(ctx).Info(logs.BucketIsCreated, zap.Stringer("container_id", bktInfo.CID))
|
h.reqLogger(ctx).Info(logs.BucketIsCreated, zap.Stringer("container_id", bktInfo.CID))
|
||||||
|
|
||||||
chains := bucketCannedACLToAPERules(cannedACL, reqInfo, key, bktInfo.CID)
|
chains := bucketCannedACLToAPERules(cannedACL, reqInfo, key, bktInfo.CID)
|
||||||
if err = h.ape.SaveACLChains(reqInfo.Namespace, chains); err != nil {
|
if err = h.ape.SaveACLChains(bktInfo.CID.EncodeToString(), chains); err != nil {
|
||||||
h.logAndSendError(w, "failed to add morph rule chain", reqInfo, err)
|
h.logAndSendError(w, "failed to add morph rule chain", reqInfo, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,15 +65,34 @@ func policyCheck(r *http.Request, cfg PolicyConfig) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
reqInfo := GetReqInfo(r.Context())
|
var bktInfo *data.BucketInfo
|
||||||
target := engine.NewRequestTargetWithNamespace(reqInfo.Namespace)
|
if reqType != noneType && !strings.HasSuffix(req.Operation(), CreateBucketOperation) {
|
||||||
st, found, err := cfg.Storage.IsAllowed(chain.S3, target, req)
|
bktInfo, err = cfg.BucketResolver(r.Context(), bktName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !found {
|
reqInfo := GetReqInfo(r.Context())
|
||||||
st = chain.NoRuleFound
|
targets := []engine.RequestTarget{
|
||||||
|
engine.NewRequestTargetWithNamespace(reqInfo.Namespace),
|
||||||
|
}
|
||||||
|
if bktInfo != nil {
|
||||||
|
targets = append(targets, engine.NewRequestTargetWithContainer(bktInfo.CID.EncodeToString()))
|
||||||
|
}
|
||||||
|
|
||||||
|
st := chain.NoRuleFound
|
||||||
|
for _, target := range targets {
|
||||||
|
status, found, err := cfg.Storage.IsAllowed(chain.S3, target, req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
st = status
|
||||||
|
if status != chain.Allow {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
@ -83,9 +102,9 @@ func policyCheck(r *http.Request, cfg PolicyConfig) error {
|
||||||
return apiErr.GetAPIErrorWithError(apiErr.ErrAccessDenied, fmt.Errorf("policy check: %s", st.String()))
|
return apiErr.GetAPIErrorWithError(apiErr.ErrAccessDenied, fmt.Errorf("policy check: %s", st.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
isAPE, err := isAPEBehavior(r.Context(), req, cfg, reqType, bktName)
|
isAPE := !cfg.Settings.ACLEnabled()
|
||||||
if err != nil {
|
if bktInfo != nil {
|
||||||
return err
|
isAPE = bktInfo.APEEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
if isAPE && cfg.Settings.PolicyDenyByDefault() {
|
if isAPE && cfg.Settings.PolicyDenyByDefault() {
|
||||||
|
@ -95,20 +114,6 @@ func policyCheck(r *http.Request, cfg PolicyConfig) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isAPEBehavior(ctx context.Context, req *testutil.Request, cfg PolicyConfig, reqType ReqType, bktName string) (bool, error) {
|
|
||||||
if reqType == noneType ||
|
|
||||||
strings.HasSuffix(req.Operation(), CreateBucketOperation) {
|
|
||||||
return !cfg.Settings.ACLEnabled(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
bktInfo, err := cfg.BucketResolver(ctx, bktName) // we cannot use reqInfo.BucketName because it hasn't been set yet
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return bktInfo.APEEnabled, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPolicyRequest(r *http.Request, frostfsid FrostFSIDInformer, reqType ReqType, bktName string, objName string, log *zap.Logger) (*testutil.Request, error) {
|
func getPolicyRequest(r *http.Request, frostfsid FrostFSIDInformer, reqType ReqType, bktName string, objName string, log *zap.Logger) (*testutil.Request, error) {
|
||||||
var (
|
var (
|
||||||
owner string
|
owner string
|
||||||
|
|
|
@ -196,6 +196,7 @@ func TestPolicyChecker(t *testing.T) {
|
||||||
func TestPolicyCheckerReqTypeDetermination(t *testing.T) {
|
func TestPolicyCheckerReqTypeDetermination(t *testing.T) {
|
||||||
chiRouter := prepareRouter(t)
|
chiRouter := prepareRouter(t)
|
||||||
bktName, objName := "bucket", "object"
|
bktName, objName := "bucket", "object"
|
||||||
|
createBucket(chiRouter, "", bktName)
|
||||||
|
|
||||||
policy := engineiam.Policy{
|
policy := engineiam.Policy{
|
||||||
Version: "2012-10-17",
|
Version: "2012-10-17",
|
||||||
|
|
|
@ -76,24 +76,24 @@ func (c *MorphRuleChainStorage) ListMorphRuleChains(name chain.Name, target engi
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MorphRuleChainStorage) PutBucketPolicy(ns string, cnrID cid.ID, policy []byte, chains []*chain.Chain) error {
|
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})
|
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.ContainerTarget(cnrID.EncodeToString()), Name: chain.S3})
|
||||||
|
|
||||||
tx := c.contract.StartTx()
|
tx := c.contract.StartTx()
|
||||||
tx.AddChain(policycontract.IAM, ns, getBucketPolicyName(cnrID), policy)
|
tx.AddChain(policycontract.IAM, ns, getBucketPolicyName(cnrID), policy)
|
||||||
|
|
||||||
for i := range chains {
|
for i := range chains {
|
||||||
tx.AddChain(policycontract.Namespace, ns, chains[i].ID, chains[i].Bytes())
|
tx.AddChain(policycontract.Container, cnrID.EncodeToString(), chains[i].ID, chains[i].Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.contract.SendTx(tx)
|
return c.contract.SendTx(tx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MorphRuleChainStorage) DeleteBucketPolicy(ns string, cnrID cid.ID, chainIDs []chain.ID) error {
|
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})
|
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.ContainerTarget(cnrID.EncodeToString()), Name: chain.S3})
|
||||||
|
|
||||||
tx := c.contract.StartTx()
|
tx := c.contract.StartTx()
|
||||||
for _, chainID := range chainIDs {
|
for _, chainID := range chainIDs {
|
||||||
tx.RemoveChain(policycontract.Namespace, ns, chainID)
|
tx.RemoveChain(policycontract.Container, cnrID.EncodeToString(), chainID)
|
||||||
}
|
}
|
||||||
tx.RemoveChain(policycontract.IAM, ns, getBucketPolicyName(cnrID))
|
tx.RemoveChain(policycontract.IAM, ns, getBucketPolicyName(cnrID))
|
||||||
|
|
||||||
|
@ -104,13 +104,13 @@ func (c *MorphRuleChainStorage) GetBucketPolicy(ns string, cnrID cid.ID) ([]byte
|
||||||
return c.contract.GetChain(policycontract.IAM, ns, getBucketPolicyName(cnrID))
|
return c.contract.GetChain(policycontract.IAM, ns, getBucketPolicyName(cnrID))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MorphRuleChainStorage) SaveACLChains(ns string, chains []*chain.Chain) error {
|
func (c *MorphRuleChainStorage) SaveACLChains(cid string, chains []*chain.Chain) error {
|
||||||
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.NamespaceTarget(ns), Name: chain.S3})
|
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.ContainerTarget(cid), Name: chain.S3})
|
||||||
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.NamespaceTarget(ns), Name: chain.Ingress})
|
c.cache.Delete(cache.MorphPolicyCacheKey{Target: engine.ContainerTarget(cid), Name: chain.Ingress})
|
||||||
|
|
||||||
tx := c.contract.StartTx()
|
tx := c.contract.StartTx()
|
||||||
for i := range chains {
|
for i := range chains {
|
||||||
tx.AddChain(policycontract.Namespace, ns, chains[i].ID, chains[i].Bytes())
|
tx.AddChain(policycontract.Container, cid, chains[i].ID, chains[i].Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.contract.SendTx(tx)
|
return c.contract.SendTx(tx)
|
||||||
|
|
Loading…
Reference in a new issue