Skip to content

Commit

Permalink
[FAB-5752] Gossip identity expiration II
Browse files Browse the repository at this point in the history
This commit adds a new method (and its implementation) to
the MessageCryptoService:
	Expiration(peerIdentity PeerIdentityType) (time.Time, error)

In the next commit I would adjust gossip to make use of this method

Change-Id: Idbdf1ba3b238a122e9d2db0b84016eb7cc6490a7
Signed-off-by: yacovm <yacovm@il.ibm.com>
  • Loading branch information
yacovm committed Aug 30, 2017
1 parent 0a03e39 commit e16c485
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 5 deletions.
4 changes: 4 additions & 0 deletions core/deliverservice/blocksprovider/blocksprovider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ type mockMCS struct {
mock.Mock
}

func (*mockMCS) Expiration(peerIdentity api.PeerIdentityType) (time.Time, error) {
return time.Now().Add(time.Hour), nil
}

func (*mockMCS) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common2.PKIidType {
return common2.PKIidType("pkiID")
}
Expand Down
4 changes: 4 additions & 0 deletions core/deliverservice/deliveryclient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ func (mock *mockBlocksDelivererFactory) Create() (blocksprovider.BlocksDeliverer
type mockMCS struct {
}

func (*mockMCS) Expiration(peerIdentity api.PeerIdentityType) (time.Time, error) {
return time.Now().Add(time.Hour), nil
}

func (*mockMCS) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType {
return common.PKIidType("pkiID")
}
Expand Down
11 changes: 11 additions & 0 deletions gossip/api/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ SPDX-License-Identifier: Apache-2.0
package api

import (
"time"

"github.com/hyperledger/fabric/gossip/common"
"google.golang.org/grpc"
)
Expand Down Expand Up @@ -47,6 +49,15 @@ type MessageCryptoService interface {
// If the identity is invalid, revoked, expired it returns an error.
// Else, returns nil
ValidateIdentity(peerIdentity PeerIdentityType) error

// Expiration returns:
// - The time when the identity expires, nil
// In case it can expire
// - A zero value time.Time, nil
// in case it cannot expire
// - A zero value, error in case it cannot be
// determined if the identity can expire or not
Expiration(peerIdentity PeerIdentityType) (time.Time, error)
}

// PeerIdentityType is the peer's certificate
Expand Down
4 changes: 4 additions & 0 deletions gossip/comm/comm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ var (
type naiveSecProvider struct {
}

func (*naiveSecProvider) Expiration(peerIdentity api.PeerIdentityType) (time.Time, error) {
return time.Now().Add(time.Hour), nil
}

func (*naiveSecProvider) ValidateIdentity(peerIdentity api.PeerIdentityType) error {
return nil
}
Expand Down
4 changes: 4 additions & 0 deletions gossip/gossip/channel/channel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ type cryptoService struct {
mock.Mock
}

func (cs *cryptoService) Expiration(peerIdentity api.PeerIdentityType) (time.Time, error) {
return time.Now().Add(time.Hour), nil
}

func (cs *cryptoService) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType {
panic("Should not be called in this test")
}
Expand Down
4 changes: 4 additions & 0 deletions gossip/gossip/gossip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ func (cs *naiveCryptoService) VerifyByChannel(_ common.ChainID, identity api.Pee
return errors.New("Forbidden")
}

func (*naiveCryptoService) Expiration(peerIdentity api.PeerIdentityType) (time.Time, error) {
return time.Time{}, nil
}

func (cs *naiveCryptoService) ValidateIdentity(peerIdentity api.PeerIdentityType) error {
cs.RLock()
defer cs.RUnlock()
Expand Down
4 changes: 4 additions & 0 deletions gossip/gossip/orgs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ type configurableCryptoService struct {
m map[string]api.OrgIdentityType
}

func (c *configurableCryptoService) Expiration(peerIdentity api.PeerIdentityType) (time.Time, error) {
return time.Now().Add(time.Hour), nil
}

func (c *configurableCryptoService) putInOrg(port int, org string) {
identity := fmt.Sprintf("localhost:%d", port)
c.m[identity] = api.OrgIdentityType(org)
Expand Down
5 changes: 4 additions & 1 deletion gossip/identity/identity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"errors"
"fmt"
"testing"

"time"

"github.com/hyperledger/fabric/gossip/api"
Expand All @@ -35,6 +34,10 @@ func init() {
util.SetupTestLogging()
}

func (cs *naiveCryptoService) Expiration(peerIdentity api.PeerIdentityType) (time.Time, error) {
return time.Time{}, nil
}

func (cs *naiveCryptoService) ValidateIdentity(peerIdentity api.PeerIdentityType) error {
if _, isRevoked := cs.revokedIdentities[string(cs.GetPKIidOfCert(peerIdentity))]; isRevoked {
return errors.New("revoked")
Expand Down
6 changes: 6 additions & 0 deletions gossip/integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"strings"
"testing"

"time"

"github.com/hyperledger/fabric/core/config"
"github.com/hyperledger/fabric/gossip/api"
"github.com/hyperledger/fabric/gossip/common"
Expand Down Expand Up @@ -102,6 +104,10 @@ func (sa *secAdviser) OrgByPeerIdentity(api.PeerIdentityType) api.OrgIdentityTyp
type cryptoService struct {
}

func (s *cryptoService) Expiration(peerIdentity api.PeerIdentityType) (time.Time, error) {
return time.Now().Add(time.Hour), nil
}

func (s *cryptoService) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType {
return common.PKIidType(peerIdentity)
}
Expand Down
4 changes: 4 additions & 0 deletions gossip/service/gossip_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,10 @@ func (*orgCryptoService) Verify(joinChanMsg api.JoinChannelMessage) error {
return nil
}

func (naiveCryptoService) Expiration(peerIdentity api.PeerIdentityType) (time.Time, error) {
return time.Now().Add(time.Hour), nil
}

// VerifyByChannel verifies a peer's signature on a message in the context
// of a specific channel
func (*naiveCryptoService) VerifyByChannel(_ gossipCommon.ChainID, _ api.PeerIdentityType, _, _ []byte) error {
Expand Down
4 changes: 4 additions & 0 deletions gossip/state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ type cryptoServiceMock struct {
acceptor peerIdentityAcceptor
}

func (cryptoServiceMock) Expiration(peerIdentity api.PeerIdentityType) (time.Time, error) {
return time.Now().Add(time.Hour), nil
}

// GetPKIidOfCert returns the PKI-ID of a peer's identity
func (*cryptoServiceMock) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType {
return common.PKIidType(peerIdentity)
Expand Down
14 changes: 12 additions & 2 deletions peer/gossip/mcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ package gossip

import (
"bytes"
"errors"
"fmt"
"time"

"github.com/hyperledger/fabric/bccsp"
"github.com/hyperledger/fabric/bccsp/factory"
Expand All @@ -33,6 +33,7 @@ import (
"github.com/hyperledger/fabric/msp/mgmt"
pcommon "github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/utils"
"github.com/pkg/errors"
)

var mcsLogger = flogging.MustGetLogger("peer/gossip/mcs")
Expand All @@ -58,7 +59,7 @@ type mspMessageCryptoService struct {
// 1. a policies.ChannelPolicyManagerGetter that gives access to the policy manager of a given channel via the Manager method.
// 2. an instance of crypto.LocalSigner
// 3. an identity deserializer manager
func NewMCS(channelPolicyManagerGetter policies.ChannelPolicyManagerGetter, localSigner crypto.LocalSigner, deserializer mgmt.DeserializersManager) api.MessageCryptoService {
func NewMCS(channelPolicyManagerGetter policies.ChannelPolicyManagerGetter, localSigner crypto.LocalSigner, deserializer mgmt.DeserializersManager) *mspMessageCryptoService {
return &mspMessageCryptoService{channelPolicyManagerGetter: channelPolicyManagerGetter, localSigner: localSigner, deserializer: deserializer}
}

Expand Down Expand Up @@ -255,6 +256,15 @@ func (s *mspMessageCryptoService) VerifyByChannel(chainID common.ChainID, peerId
)
}

func (s *mspMessageCryptoService) Expiration(peerIdentity api.PeerIdentityType) (time.Time, error) {
id, _, err := s.getValidatedIdentity(peerIdentity)
if err != nil {
return time.Time{}, errors.Wrap(err, "Unable to extract msp.Identity from peer Identity")
}
return id.ExpiresAt(), nil

}

func (s *mspMessageCryptoService) getValidatedIdentity(peerIdentity api.PeerIdentityType) (msp.Identity, common.ChainID, error) {
// Validate arguments
if len(peerIdentity) == 0 {
Expand Down
61 changes: 61 additions & 0 deletions peer/gossip/mcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package gossip
import (
"reflect"
"testing"
"time"

"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/bccsp"
Expand All @@ -33,6 +34,7 @@ import (
"github.com/hyperledger/fabric/msp/mgmt"
"github.com/hyperledger/fabric/peer/gossip/mocks"
"github.com/hyperledger/fabric/protos/common"
pmsp "github.com/hyperledger/fabric/protos/msp"
protospeer "github.com/hyperledger/fabric/protos/peer"
"github.com/hyperledger/fabric/protos/utils"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -254,3 +256,62 @@ func mockBlock(t *testing.T, channel string, seqNum uint64, localSigner crypto.L

return blockRaw, msg
}

func TestExpiration(t *testing.T) {
expirationDate := time.Now().Add(time.Minute)
id1 := &pmsp.SerializedIdentity{
Mspid: "X509BasedMSP",
IdBytes: []byte("X509BasedIdentity"),
}

x509IdentityBytes, _ := proto.Marshal(id1)

id2 := &pmsp.SerializedIdentity{
Mspid: "nonX509BasedMSP",
IdBytes: []byte("nonX509RawIdentity"),
}

nonX509IdentityBytes, _ := proto.Marshal(id2)

deserializersManager := &mocks.DeserializersManager{
LocalDeserializer: &mocks.IdentityDeserializer{
Identity: []byte{1, 2, 3},
Msg: []byte{1, 2, 3},
},
ChannelDeserializers: map[string]msp.IdentityDeserializer{
"X509BasedMSP": &mocks.IdentityDeserializerWithExpiration{
Expiration: expirationDate,
IdentityDeserializer: &mocks.IdentityDeserializer{
Identity: x509IdentityBytes,
Msg: []byte("x509IdentityBytes"),
},
},
"nonX509BasedMSP": &mocks.IdentityDeserializer{
Identity: nonX509IdentityBytes,
Msg: []byte("nonX509IdentityBytes"),
},
},
}
msgCryptoService := NewMCS(
&mocks.ChannelPolicyManagerGetterWithManager{},
&mockscrypto.LocalSigner{Identity: []byte("Yacov")},
deserializersManager,
)

// Green path I check the expiration date is as expected
exp, err := msgCryptoService.Expiration(x509IdentityBytes)
assert.NoError(t, err)
assert.Equal(t, expirationDate.Second(), exp.Second())

// Green path II - a non-x509 identity has a zero expiration time
exp, err = msgCryptoService.Expiration(nonX509IdentityBytes)
assert.NoError(t, err)
assert.Zero(t, exp)

// Bad path I - corrupt the x509 identity and make sure error is returned
x509IdentityBytes = append(x509IdentityBytes, 0, 0, 0, 0, 0, 0)
exp, err = msgCryptoService.Expiration(x509IdentityBytes)
assert.Error(t, err)
assert.Contains(t, err.Error(), "No MSP found able to do that")
assert.Zero(t, exp)
}
19 changes: 17 additions & 2 deletions peer/gossip/mocks/mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,20 @@ func (m *DeserializersManager) GetChannelDeserializers() map[string]msp.Identity
return m.ChannelDeserializers
}

type IdentityDeserializerWithExpiration struct {
*IdentityDeserializer
Expiration time.Time
}

func (d *IdentityDeserializerWithExpiration) DeserializeIdentity(serializedIdentity []byte) (msp.Identity, error) {
id, err := d.IdentityDeserializer.DeserializeIdentity(serializedIdentity)
if err != nil {
return nil, err
}
id.(*Identity).expirationDate = d.Expiration
return id, nil
}

type IdentityDeserializer struct {
Identity []byte
Msg []byte
Expand All @@ -107,11 +121,12 @@ func (d *IdentityDeserializer) DeserializeIdentity(serializedIdentity []byte) (m
}

type Identity struct {
Msg []byte
expirationDate time.Time
Msg []byte
}

func (id *Identity) ExpiresAt() time.Time {
return time.Time{}
return id.expirationDate
}

func (id *Identity) SatisfiesPrincipal(*mspproto.MSPPrincipal) error {
Expand Down

0 comments on commit e16c485

Please sign in to comment.