Compare commits

...

4 commits

Author SHA1 Message Date
9f28e2bf0c [#XX] Fix sdk client
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-02-21 15:27:46 +03:00
Denis Kirillov
6f991ab762 services/tree: Use bearer owner as signer
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-02-21 12:21:46 +03:00
fe56f11edc Disable container owner check in tree service
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-02-21 11:47:30 +03:00
56f12c77b9 Allow Impersonate
Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-02-21 11:47:28 +03:00
6 changed files with 64 additions and 25 deletions

View file

@ -48,7 +48,7 @@ func GetSDKClient(cmd *cobra.Command, key *ecdsa.PrivateKey, addr network.Addres
) )
prmInit.SetDefaultPrivateKey(*key) prmInit.SetDefaultPrivateKey(*key)
prmInit.ResolveNeoFSFailures() prmInit.ResolveFrostFSFailures()
prmDial.SetServerURI(addr.URIAddr()) prmDial.SetServerURI(addr.URIAddr())
if timeout := viper.GetDuration(commonflags.Timeout); timeout > 0 { if timeout := viper.GetDuration(commonflags.Timeout); timeout > 0 {
// In CLI we can only set a timeout for the whole operation. // In CLI we can only set a timeout for the whole operation.

12
go.mod
View file

@ -39,10 +39,15 @@ require (
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
) )
replace (
github.com/TrueCloudLab/frostfs-api-go/v2 v2.0.0-20221212144048-1351b6656d68 => github.com/KirillovDenis/frostfs-api-go/v2 v2.11.2-0.20230221082308-ac00938fa447
github.com/TrueCloudLab/frostfs-sdk-go v0.0.0-20221214065929-4c779423f556 => github.com/KirillovDenis/frostfs-sdk-go v0.0.0-20230221122223-9424a67fb108
)
require ( require (
github.com/TrueCloudLab/frostfs-crypto v0.5.0 // indirect github.com/TrueCloudLab/frostfs-crypto v0.5.0 // indirect
github.com/TrueCloudLab/rfc6979 v0.3.0 // indirect github.com/TrueCloudLab/rfc6979 v0.3.0 // indirect
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20221202181307-76fa05c21b12 // indirect
github.com/benbjohnson/clock v1.1.0 // indirect github.com/benbjohnson/clock v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect
@ -54,7 +59,7 @@ require (
github.com/golang/snappy v0.0.3 // indirect github.com/golang/snappy v0.0.3 // indirect
github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-querystring v1.1.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect github.com/gorilla/websocket v1.4.2 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/golang-lru v0.6.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/holiman/uint256 v1.2.0 // indirect github.com/holiman/uint256 v1.2.0 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.0.1 // indirect
@ -89,8 +94,9 @@ require (
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 // indirect github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 // indirect
github.com/twmb/murmur3 v1.1.5 // indirect github.com/twmb/murmur3 v1.1.5 // indirect
github.com/urfave/cli v1.22.5 // indirect github.com/urfave/cli v1.22.5 // indirect
go.uber.org/multierr v1.8.0 // indirect go.uber.org/multierr v1.9.0 // indirect
golang.org/x/crypto v0.4.0 // indirect golang.org/x/crypto v0.4.0 // indirect
golang.org/x/exp v0.0.0-20221227203929-1b447090c38c // indirect
golang.org/x/net v0.4.0 // indirect golang.org/x/net v0.4.0 // indirect
golang.org/x/sync v0.1.0 // indirect golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.3.0 // indirect golang.org/x/sys v0.3.0 // indirect

BIN
go.sum

Binary file not shown.

View file

@ -124,15 +124,17 @@ func (c *Checker) CheckEACL(msg interface{}, reqInfo v2.RequestInfo) error {
return nil return nil
} }
bearerTok := reqInfo.Bearer()
impersonate := bearerTok != nil && bearerTok.Impersonate()
// if bearer token is not allowed, then ignore it // if bearer token is not allowed, then ignore it
if !basicACL.AllowedBearerRules(reqInfo.Operation()) { if impersonate || !basicACL.AllowedBearerRules(reqInfo.Operation()) {
reqInfo.CleanBearer() reqInfo.CleanBearer()
} }
var table eaclSDK.Table var table eaclSDK.Table
cnr := reqInfo.ContainerID() cnr := reqInfo.ContainerID()
bearerTok := reqInfo.Bearer()
if bearerTok == nil { if bearerTok == nil {
eaclInfo, err := c.eaclSrc.GetEACL(cnr) eaclInfo, err := c.eaclSrc.GetEACL(cnr)
if err != nil { if err != nil {

View file

@ -2,6 +2,7 @@ package v2
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"crypto/elliptic"
"fmt" "fmt"
sessionV2 "github.com/TrueCloudLab/frostfs-api-go/v2/session" sessionV2 "github.com/TrueCloudLab/frostfs-api-go/v2/session"
@ -113,6 +114,12 @@ func (r MetaWithToken) RequestOwner() (*user.ID, *keys.PublicKey, error) {
return nil, nil, errEmptyVerificationHeader return nil, nil, errEmptyVerificationHeader
} }
if r.bearer != nil && r.bearer.Impersonate() {
issuer := bearer.ResolveIssuer(*r.bearer)
pubKey, err := keys.NewPublicKeyFromBytes(r.bearer.SigningKeyBytes(), elliptic.P256())
return &issuer, pubKey, err
}
// if session token is presented, use it as truth source // if session token is presented, use it as truth source
if r.token != nil { if r.token != nil {
// verify signature of session token // verify signature of session token

View file

@ -56,7 +56,23 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op
return fmt.Errorf("can't get container %s: %w", cid, err) return fmt.Errorf("can't get container %s: %w", cid, err)
} }
role, err := roleFromReq(cnr, req) eaclOp := eACLOp(op)
var bt *bearer.Token
if len(rawBearer) > 0 {
bt = new(bearer.Token)
if err = bt.Unmarshal(rawBearer); err != nil {
return eACLErr(eaclOp, fmt.Errorf("invalid bearer token: %w", err))
}
if !bt.VerifySignature() {
return eACLErr(eaclOp, errBearerSignature)
}
if !bt.AssertContainer(cid) {
return eACLErr(eaclOp, errBearerWrongContainer)
}
}
role, err := roleFromReq(cnr, req, bt)
if err != nil { if err != nil {
return fmt.Errorf("can't get request role: %w", err) return fmt.Errorf("can't get request role: %w", err)
} }
@ -71,8 +87,6 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op
return nil return nil
} }
eaclOp := eACLOp(op)
var tableFromBearer bool var tableFromBearer bool
if len(rawBearer) != 0 { if len(rawBearer) != 0 {
if !basicACL.AllowedBearerRules(op) { if !basicACL.AllowedBearerRules(op) {
@ -86,22 +100,25 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op
} }
var tb eacl.Table var tb eacl.Table
signer := req.GetSignature().GetKey()
if tableFromBearer { if tableFromBearer {
var bt bearer.Token if bt.Impersonate() {
if err = bt.Unmarshal(rawBearer); err != nil { tbCore, err := s.eaclSource.GetEACL(cid)
return eACLErr(eaclOp, fmt.Errorf("invalid bearer token: %w", err)) if err != nil {
} if client.IsErrEACLNotFound(err) {
if !bearer.ResolveIssuer(bt).Equals(cnr.Value.Owner()) { return nil
return eACLErr(eaclOp, errBearerWrongOwner) }
}
if !bt.AssertContainer(cid) {
return eACLErr(eaclOp, errBearerWrongContainer)
}
if !bt.VerifySignature() {
return eACLErr(eaclOp, errBearerSignature)
}
tb = bt.EACLTable() return fmt.Errorf("get eACL table: %w", err)
}
tb = *tbCore.Value
signer = bt.SigningKeyBytes()
} else {
if !bearer.ResolveIssuer(*bt).Equals(cnr.Value.Owner()) {
return eACLErr(eaclOp, errBearerWrongOwner)
}
tb = bt.EACLTable()
}
} else { } else {
tbCore, err := s.eaclSource.GetEACL(cid) tbCore, err := s.eaclSource.GetEACL(cid)
if err != nil { if err != nil {
@ -115,7 +132,7 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op
tb = *tbCore.Value tb = *tbCore.Value
} }
return checkEACL(tb, req.GetSignature().GetKey(), eACLRole(role), eaclOp) return checkEACL(tb, signer, eACLRole(role), eaclOp)
} }
func verifyMessage(m message) error { func verifyMessage(m message) error {
@ -168,7 +185,7 @@ func SignMessage(m message, key *ecdsa.PrivateKey) error {
return nil return nil
} }
func roleFromReq(cnr *core.Container, req message) (acl.Role, error) { func roleFromReq(cnr *core.Container, req message, bt *bearer.Token) (acl.Role, error) {
role := acl.RoleOthers role := acl.RoleOthers
owner := cnr.Value.Owner() owner := cnr.Value.Owner()
@ -177,6 +194,13 @@ func roleFromReq(cnr *core.Container, req message) (acl.Role, error) {
return role, fmt.Errorf("invalid public key: %w", err) return role, fmt.Errorf("invalid public key: %w", err)
} }
if bt != nil && bt.Impersonate() {
pub, err = keys.NewPublicKeyFromBytes(bt.SigningKeyBytes(), elliptic.P256())
if err != nil {
return role, fmt.Errorf("invalid public key: %w", err)
}
}
var reqSigner user.ID var reqSigner user.ID
user.IDFromKey(&reqSigner, (ecdsa.PublicKey)(*pub)) user.IDFromKey(&reqSigner, (ecdsa.PublicKey)(*pub))