diff --git a/pkg/services/tree/signature.go b/pkg/services/tree/signature.go index e861541f..4aacbc3b 100644 --- a/pkg/services/tree/signature.go +++ b/pkg/services/tree/signature.go @@ -57,7 +57,23 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op 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.AssertContainer(cid) { + return eACLErr(eaclOp, errBearerWrongContainer) + } + if !bt.VerifySignature() { + return eACLErr(eaclOp, errBearerSignature) + } + } + + role, err := roleFromReq(cnr, req, bt) if err != nil { return fmt.Errorf("can't get request role: %w", err) } @@ -72,8 +88,6 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op return nil } - eaclOp := eACLOp(op) - var tableFromBearer bool if len(rawBearer) != 0 { if !basicACL.AllowedBearerRules(op) { @@ -88,29 +102,22 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op var tb eacl.Table if tableFromBearer { - var bt bearer.Token - if err = bt.Unmarshal(rawBearer); err != nil { - return eACLErr(eaclOp, fmt.Errorf("invalid bearer token: %w", err)) + if bt.Impersonate() { + tbCore, err := s.eaclSource.GetEACL(cid) + if err != nil { + return handleGetEACLError(err) + } + tb = *tbCore.Value + } else { + if !bearer.ResolveIssuer(*bt).Equals(cnr.Value.Owner()) { + return eACLErr(eaclOp, errBearerWrongOwner) + } + tb = bt.EACLTable() } - if !bearer.ResolveIssuer(bt).Equals(cnr.Value.Owner()) { - return eACLErr(eaclOp, errBearerWrongOwner) - } - if !bt.AssertContainer(cid) { - return eACLErr(eaclOp, errBearerWrongContainer) - } - if !bt.VerifySignature() { - return eACLErr(eaclOp, errBearerSignature) - } - - tb = bt.EACLTable() } else { tbCore, err := s.eaclSource.GetEACL(cid) if err != nil { - if client.IsErrEACLNotFound(err) { - return nil - } - - return fmt.Errorf("get eACL table: %w", err) + return handleGetEACLError(err) } tb = *tbCore.Value @@ -119,6 +126,14 @@ func (s *Service) verifyClient(req message, cid cidSDK.ID, rawBearer []byte, op return checkEACL(tb, req.GetSignature().GetKey(), eACLRole(role), eaclOp) } +func handleGetEACLError(err error) error { + if client.IsErrEACLNotFound(err) { + return nil + } + + return fmt.Errorf("get eACL table: %w", err) +} + func verifyMessage(m message) error { binBody, err := m.ReadSignedData(nil) if err != nil { @@ -169,11 +184,16 @@ func SignMessage(m message, key *ecdsa.PrivateKey) error { 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 owner := cnr.Value.Owner() - pub, err := keys.NewPublicKeyFromBytes(req.GetSignature().GetKey(), elliptic.P256()) + rawKey := req.GetSignature().GetKey() + if bt != nil && bt.Impersonate() { + rawKey = bt.SigningKeyBytes() + } + + pub, err := keys.NewPublicKeyFromBytes(rawKey, elliptic.P256()) if err != nil { return role, fmt.Errorf("invalid public key: %w", err) }