Fill APE Request proprties with source IP in services #1142
4 changed files with 37 additions and 26 deletions
|
@ -1,8 +1,10 @@
|
||||||
package tree
|
package tree
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/converter"
|
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/converter"
|
||||||
|
@ -14,11 +16,13 @@ import (
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
apechain "git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
|
||||||
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
"git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine"
|
||||||
|
commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common"
|
||||||
nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
|
nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"google.golang.org/grpc/peer"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Service) checkAPE(container *core.Container, cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey) error {
|
func (s *Service) checkAPE(ctx context.Context, container *core.Container, cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey) error {
|
||||||
namespace := ""
|
namespace := ""
|
||||||
cntNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(container.Value).Zone(), ".ns")
|
cntNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(container.Value).Zone(), ".ns")
|
||||||
if hasNamespace {
|
if hasNamespace {
|
||||||
|
@ -41,6 +45,11 @@ func (s *Service) checkAPE(container *core.Container, cid cid.ID, operation acl.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return apeErr(err)
|
return apeErr(err)
|
||||||
}
|
}
|
||||||
|
if p, ok := peer.FromContext(ctx); ok {
|
||||||
|
if tcpAddr, ok := p.Addr.(*net.TCPAddr); ok {
|
||||||
|
reqProps[commonschema.PropertyKeyFrostFSSourceIP] = tcpAddr.IP.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var resourceName string
|
var resourceName string
|
||||||
if namespace == "root" || namespace == "" {
|
if namespace == "root" || namespace == "" {
|
||||||
|
|
|
@ -105,7 +105,7 @@ func (s *Service) Add(ctx context.Context, req *AddRequest) (*AddResponse, error
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err := s.verifyClient(req, cid, b.GetBearerToken(), acl.OpObjectPut)
|
err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectPut)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -157,7 +157,7 @@ func (s *Service) AddByPath(ctx context.Context, req *AddByPathRequest) (*AddByP
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err := s.verifyClient(req, cid, b.GetBearerToken(), acl.OpObjectPut)
|
err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectPut)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,7 @@ func (s *Service) Remove(ctx context.Context, req *RemoveRequest) (*RemoveRespon
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err := s.verifyClient(req, cid, b.GetBearerToken(), acl.OpObjectPut)
|
err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectPut)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ func (s *Service) Move(ctx context.Context, req *MoveRequest) (*MoveResponse, er
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err := s.verifyClient(req, cid, b.GetBearerToken(), acl.OpObjectPut)
|
err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectPut)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -326,7 +326,7 @@ func (s *Service) GetNodeByPath(ctx context.Context, req *GetNodeByPathRequest)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err := s.verifyClient(req, cid, b.GetBearerToken(), acl.OpObjectGet)
|
err := s.verifyClient(ctx, req, cid, b.GetBearerToken(), acl.OpObjectGet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -408,7 +408,7 @@ func (s *Service) GetSubTree(req *GetSubTreeRequest, srv TreeService_GetSubTreeS
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err := s.verifyClient(req, cid, b.GetBearerToken(), acl.OpObjectGet)
|
err := s.verifyClient(srv.Context(), req, cid, b.GetBearerToken(), acl.OpObjectGet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package tree
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
"errors"
|
"errors"
|
||||||
|
@ -48,7 +49,7 @@ var (
|
||||||
// Operation must be one of:
|
// Operation must be one of:
|
||||||
// - 1. ObjectPut;
|
// - 1. ObjectPut;
|
||||||
// - 2. ObjectGet.
|
// - 2. ObjectGet.
|
||||||
func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op acl.Op) error {
|
func (s *Service) verifyClient(ctx context.Context, req message, cid cidSDK.ID, rawBearer []byte, op acl.Op) error {
|
||||||
err := verifyMessage(req)
|
err := verifyMessage(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -83,7 +84,7 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op
|
||||||
// FIXME(@aarifullin): tree service temporiraly performs APE checks on
|
// FIXME(@aarifullin): tree service temporiraly performs APE checks on
|
||||||
// object verbs, because tree verbs have not been introduced yet.
|
// object verbs, because tree verbs have not been introduced yet.
|
||||||
if basicACL == 0x0 {
|
if basicACL == 0x0 {
|
||||||
return s.checkAPE(cnr, cid, op, role, pubKey)
|
return s.checkAPE(ctx, cnr, cid, op, role, pubKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !basicACL.IsOpAllowed(op, role) {
|
if !basicACL.IsOpAllowed(op, role) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package tree
|
package tree
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"errors"
|
"errors"
|
||||||
|
@ -132,26 +133,26 @@ func TestMessageSign(t *testing.T) {
|
||||||
cnr.Value.SetBasicACL(acl.PublicRW)
|
cnr.Value.SetBasicACL(acl.PublicRW)
|
||||||
|
|
||||||
t.Run("missing signature, no panic", func(t *testing.T) {
|
t.Run("missing signature, no panic", func(t *testing.T) {
|
||||||
require.Error(t, s.verifyClient(req, cid2, nil, op))
|
require.Error(t, s.verifyClient(context.Background(), req, cid2, nil, op))
|
||||||
})
|
})
|
||||||
|
|
||||||
require.NoError(t, SignMessage(req, &privs[0].PrivateKey))
|
require.NoError(t, SignMessage(req, &privs[0].PrivateKey))
|
||||||
require.NoError(t, s.verifyClient(req, cid1, nil, op))
|
require.NoError(t, s.verifyClient(context.Background(), req, cid1, nil, op))
|
||||||
|
|
||||||
t.Run("invalid CID", func(t *testing.T) {
|
t.Run("invalid CID", func(t *testing.T) {
|
||||||
require.Error(t, s.verifyClient(req, cid2, nil, op))
|
require.Error(t, s.verifyClient(context.Background(), req, cid2, nil, op))
|
||||||
})
|
})
|
||||||
|
|
||||||
cnr.Value.SetBasicACL(acl.Private)
|
cnr.Value.SetBasicACL(acl.Private)
|
||||||
|
|
||||||
t.Run("extension disabled", func(t *testing.T) {
|
t.Run("extension disabled", func(t *testing.T) {
|
||||||
require.NoError(t, SignMessage(req, &privs[0].PrivateKey))
|
require.NoError(t, SignMessage(req, &privs[0].PrivateKey))
|
||||||
require.Error(t, s.verifyClient(req, cid2, nil, op))
|
require.Error(t, s.verifyClient(context.Background(), req, cid2, nil, op))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("invalid key", func(t *testing.T) {
|
t.Run("invalid key", func(t *testing.T) {
|
||||||
require.NoError(t, SignMessage(req, &privs[1].PrivateKey))
|
require.NoError(t, SignMessage(req, &privs[1].PrivateKey))
|
||||||
require.Error(t, s.verifyClient(req, cid1, nil, op))
|
require.Error(t, s.verifyClient(context.Background(), req, cid1, nil, op))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("bearer", func(t *testing.T) {
|
t.Run("bearer", func(t *testing.T) {
|
||||||
|
@ -164,7 +165,7 @@ func TestMessageSign(t *testing.T) {
|
||||||
t.Run("invalid bearer", func(t *testing.T) {
|
t.Run("invalid bearer", func(t *testing.T) {
|
||||||
req.Body.BearerToken = []byte{0xFF}
|
req.Body.BearerToken = []byte{0xFF}
|
||||||
require.NoError(t, SignMessage(req, &privs[0].PrivateKey))
|
require.NoError(t, SignMessage(req, &privs[0].PrivateKey))
|
||||||
require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("invalid bearer CID", func(t *testing.T) {
|
t.Run("invalid bearer CID", func(t *testing.T) {
|
||||||
|
@ -173,7 +174,7 @@ func TestMessageSign(t *testing.T) {
|
||||||
req.Body.BearerToken = bt.Marshal()
|
req.Body.BearerToken = bt.Marshal()
|
||||||
|
|
||||||
require.NoError(t, SignMessage(req, &privs[1].PrivateKey))
|
require.NoError(t, SignMessage(req, &privs[1].PrivateKey))
|
||||||
require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
||||||
})
|
})
|
||||||
t.Run("invalid bearer owner", func(t *testing.T) {
|
t.Run("invalid bearer owner", func(t *testing.T) {
|
||||||
bt := testBearerToken(cid1, privs[1].PublicKey(), privs[2].PublicKey())
|
bt := testBearerToken(cid1, privs[1].PublicKey(), privs[2].PublicKey())
|
||||||
|
@ -181,7 +182,7 @@ func TestMessageSign(t *testing.T) {
|
||||||
req.Body.BearerToken = bt.Marshal()
|
req.Body.BearerToken = bt.Marshal()
|
||||||
|
|
||||||
require.NoError(t, SignMessage(req, &privs[1].PrivateKey))
|
require.NoError(t, SignMessage(req, &privs[1].PrivateKey))
|
||||||
require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
||||||
})
|
})
|
||||||
t.Run("invalid bearer signature", func(t *testing.T) {
|
t.Run("invalid bearer signature", func(t *testing.T) {
|
||||||
bt := testBearerToken(cid1, privs[1].PublicKey(), privs[2].PublicKey())
|
bt := testBearerToken(cid1, privs[1].PublicKey(), privs[2].PublicKey())
|
||||||
|
@ -193,7 +194,7 @@ func TestMessageSign(t *testing.T) {
|
||||||
req.Body.BearerToken = bv2.StableMarshal(nil)
|
req.Body.BearerToken = bv2.StableMarshal(nil)
|
||||||
|
|
||||||
require.NoError(t, SignMessage(req, &privs[1].PrivateKey))
|
require.NoError(t, SignMessage(req, &privs[1].PrivateKey))
|
||||||
require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("impersonate", func(t *testing.T) {
|
t.Run("impersonate", func(t *testing.T) {
|
||||||
|
@ -205,8 +206,8 @@ func TestMessageSign(t *testing.T) {
|
||||||
req.Body.BearerToken = bt.Marshal()
|
req.Body.BearerToken = bt.Marshal()
|
||||||
|
|
||||||
require.NoError(t, SignMessage(req, &privs[0].PrivateKey))
|
require.NoError(t, SignMessage(req, &privs[0].PrivateKey))
|
||||||
require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
||||||
require.NoError(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet))
|
require.NoError(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet))
|
||||||
})
|
})
|
||||||
|
|
||||||
bt := testBearerToken(cid1, privs[1].PublicKey(), privs[2].PublicKey())
|
bt := testBearerToken(cid1, privs[1].PublicKey(), privs[2].PublicKey())
|
||||||
|
@ -216,18 +217,18 @@ func TestMessageSign(t *testing.T) {
|
||||||
|
|
||||||
t.Run("put and get", func(t *testing.T) {
|
t.Run("put and get", func(t *testing.T) {
|
||||||
require.NoError(t, SignMessage(req, &privs[1].PrivateKey))
|
require.NoError(t, SignMessage(req, &privs[1].PrivateKey))
|
||||||
require.NoError(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
require.NoError(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
||||||
require.NoError(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet))
|
require.NoError(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet))
|
||||||
})
|
})
|
||||||
t.Run("only get", func(t *testing.T) {
|
t.Run("only get", func(t *testing.T) {
|
||||||
require.NoError(t, SignMessage(req, &privs[2].PrivateKey))
|
require.NoError(t, SignMessage(req, &privs[2].PrivateKey))
|
||||||
require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
||||||
require.NoError(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet))
|
require.NoError(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet))
|
||||||
})
|
})
|
||||||
t.Run("none", func(t *testing.T) {
|
t.Run("none", func(t *testing.T) {
|
||||||
require.NoError(t, SignMessage(req, &privs[3].PrivateKey))
|
require.NoError(t, SignMessage(req, &privs[3].PrivateKey))
|
||||||
require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectPut))
|
||||||
require.Error(t, s.verifyClient(req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet))
|
require.Error(t, s.verifyClient(context.Background(), req, cid1, req.GetBody().GetBearerToken(), acl.OpObjectGet))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue