-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FAB-7638] Block expired x509 identities in bcast
This change set blocks expired x509 identities from succeeding broadcast, via a new envelope filter. Change-Id: I6d864b9ed3f525355e38de5c2b7b05105d079aa8 Signed-off-by: yacovm <[email protected]>
- Loading branch information
Showing
10 changed files
with
242 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package msgprocessor | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/hyperledger/fabric/common/channelconfig" | ||
"github.com/hyperledger/fabric/common/crypto" | ||
"github.com/hyperledger/fabric/protos/common" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
type resources interface { | ||
// OrdererConfig returns the config.Orderer for the channel | ||
// and whether the Orderer config exists | ||
OrdererConfig() (channelconfig.Orderer, bool) | ||
} | ||
|
||
// NewExpirationRejectRule returns a rule that rejects messages signed by identities | ||
// who's identities have expired, given the capability is active | ||
func NewExpirationRejectRule(filterSupport resources) Rule { | ||
return &expirationRejectRule{filterSupport: filterSupport} | ||
} | ||
|
||
type expirationRejectRule struct { | ||
filterSupport resources | ||
} | ||
|
||
// Apply checks whether the identity that created the envelope has expired | ||
func (exp *expirationRejectRule) Apply(message *common.Envelope) error { | ||
ordererConf, ok := exp.filterSupport.OrdererConfig() | ||
if !ok { | ||
logger.Panic("Programming error: orderer config not found") | ||
} | ||
if !ordererConf.Capabilities().ExpirationCheck() { | ||
return nil | ||
} | ||
signedData, err := message.AsSignedData() | ||
|
||
if err != nil { | ||
return errors.Errorf("could not convert message to signedData: %s", err) | ||
} | ||
expirationTime := crypto.ExpiresAt(signedData[0].Identity) | ||
// Identity cannot expire, or identity has not expired yet | ||
if expirationTime.IsZero() || time.Now().Before(expirationTime) { | ||
return nil | ||
} | ||
return errors.New("identity expired") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
/* | ||
Copyright IBM Corp. All Rights Reserved. | ||
SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
package msgprocessor | ||
|
||
import ( | ||
"io/ioutil" | ||
"path/filepath" | ||
"testing" | ||
|
||
"github.com/golang/protobuf/proto" | ||
"github.com/hyperledger/fabric/common/channelconfig" | ||
"github.com/hyperledger/fabric/common/mocks/config" | ||
"github.com/hyperledger/fabric/protos/common" | ||
"github.com/hyperledger/fabric/protos/msp" | ||
"github.com/hyperledger/fabric/protos/utils" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/mock" | ||
) | ||
|
||
func createEnvelope(t *testing.T, serializedIdentity []byte) *common.Envelope { | ||
sHdr := utils.MakeSignatureHeader(serializedIdentity, nil) | ||
hdr := utils.MakePayloadHeader(&common.ChannelHeader{}, sHdr) | ||
payload := &common.Payload{ | ||
Header: hdr, | ||
} | ||
payloadBytes, err := proto.Marshal(payload) | ||
assert.NoError(t, err) | ||
return &common.Envelope{ | ||
Payload: payloadBytes, | ||
Signature: []byte{1, 2, 3}, | ||
} | ||
} | ||
|
||
func createX509Identity(t *testing.T, certFileName string) []byte { | ||
certBytes, err := ioutil.ReadFile(filepath.Join("testdata", certFileName)) | ||
assert.NoError(t, err) | ||
sId := &msp.SerializedIdentity{ | ||
IdBytes: certBytes, | ||
} | ||
idBytes, err := proto.Marshal(sId) | ||
assert.NoError(t, err) | ||
return idBytes | ||
} | ||
|
||
func createIdemixIdentity(t *testing.T) []byte { | ||
idemixId := &msp.SerializedIdemixIdentity{ | ||
NymX: []byte{1, 2, 3}, | ||
NymY: []byte{1, 2, 3}, | ||
OU: []byte("OU1"), | ||
} | ||
idemixBytes, err := proto.Marshal(idemixId) | ||
assert.NoError(t, err) | ||
sId := &msp.SerializedIdentity{ | ||
IdBytes: idemixBytes, | ||
} | ||
idBytes, err := proto.Marshal(sId) | ||
assert.NoError(t, err) | ||
return idBytes | ||
} | ||
|
||
type resourcesMock struct { | ||
mock.Mock | ||
} | ||
|
||
func (r *resourcesMock) OrdererConfig() (channelconfig.Orderer, bool) { | ||
args := r.Called() | ||
if args.Get(1).(bool) { | ||
return args.Get(0).(channelconfig.Orderer), true | ||
} | ||
return nil, false | ||
} | ||
|
||
func TestExpirationRejectRule(t *testing.T) { | ||
activeCapability := &config.Orderer{CapabilitiesVal: &config.OrdererCapabilities{ | ||
ExpirationVal: true, | ||
}} | ||
inActiveCapability := &config.Orderer{CapabilitiesVal: &config.OrdererCapabilities{ | ||
ExpirationVal: false, | ||
}} | ||
resources := &resourcesMock{} | ||
setupMock := func() { | ||
// Odd invocations return active capability | ||
resources.On("OrdererConfig").Return(activeCapability, true).Once() | ||
// Even invocations return inactive capability | ||
resources.On("OrdererConfig").Return(inActiveCapability, true).Once() | ||
} | ||
t.Run("NoOrdererConfig", func(t *testing.T) { | ||
resources.On("OrdererConfig").Return(nil, false).Once() | ||
assert.Panics(t, func() { | ||
NewExpirationRejectRule(resources).Apply(&common.Envelope{}) | ||
}) | ||
}) | ||
t.Run("BadEnvelope", func(t *testing.T) { | ||
setupMock() | ||
err := NewExpirationRejectRule(resources).Apply(&common.Envelope{}) | ||
assert.Error(t, err) | ||
assert.Contains(t, err.Error(), "could not convert message to signedData") | ||
|
||
err = NewExpirationRejectRule(resources).Apply(&common.Envelope{}) | ||
assert.NoError(t, err) | ||
}) | ||
t.Run("ExpiredX509Identity", func(t *testing.T) { | ||
setupMock() | ||
env := createEnvelope(t, createX509Identity(t, "expiredCert.pem")) | ||
err := NewExpirationRejectRule(resources).Apply(env) | ||
assert.Error(t, err) | ||
assert.Equal(t, err.Error(), "identity expired") | ||
|
||
err = NewExpirationRejectRule(resources).Apply(env) | ||
assert.NoError(t, err) | ||
}) | ||
t.Run("IdemixIdentity", func(t *testing.T) { | ||
setupMock() | ||
env := createEnvelope(t, createIdemixIdentity(t)) | ||
assert.Nil(t, NewExpirationRejectRule(resources).Apply(env)) | ||
assert.Nil(t, NewExpirationRejectRule(resources).Apply(env)) | ||
}) | ||
t.Run("NoneExpiredX509Identity", func(t *testing.T) { | ||
setupMock() | ||
env := createEnvelope(t, createX509Identity(t, "cert.pem")) | ||
assert.Nil(t, NewExpirationRejectRule(resources).Apply(env)) | ||
assert.Nil(t, NewExpirationRejectRule(resources).Apply(env)) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
-----BEGIN CERTIFICATE----- | ||
MIICCDCCAa6gAwIBAgIRANLH5Ue5a6tHuzCQtap1BP8wCgYIKoZIzj0EAwIwZzEL | ||
MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG | ||
cmFuY2lzY28xEzARBgNVBAoTCmhybC5pYm0uaWwxFjAUBgNVBAMTDWNhLmhybC5p | ||
EwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj | ||
bzEZMBcGA1UEAwwQVXNlcjFAaHJsLmlibS5pbDBZMBMGByqGSM49AgEGCCqGSM49 | ||
AwEHA0IABE7fF65KsF0nxNgIBFVA2x/QU0LuAyuTsRaSWc/ycQAuLQfCti5bYp4W | ||
WaQUc5sBaKAmVbFQTm9RhmOhtIz7PL6jTTBLMA4GA1UdDwEB/wQEAwIHgDAMBgNV | ||
HRMBAf8EAjAAMCsGA1UdIwQkMCKAIMjiBsyFZlbO6pRxo7VgoqKhl78Ujd9sdWUk | ||
epB05fodMAoGCCqGSM49BAMCA0gAMEUCIQCiOzbaApF46NVobwh3wqHf8ID1zxja | ||
j23HPXR3FjjFZgIgXLujyDGETptNrELaytjG+dxO3Kzq/SM07K2zPUg4368= | ||
-----END CERTIFICATE----- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
-----BEGIN CERTIFICATE----- | ||
MIICCDCCAa6gAwIBAgIRANLH5Ue5a6tHuzCQtap1BP8wCgYIKoZIzj0EAwIwZzEL | ||
MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG | ||
cmFuY2lzY28xEzARBgNVBAoTCmhybC5pYm0uaWwxFjAUBgNVBAMTDWNhLmhybC5p | ||
Ym0uaWwwHhcNMTcwODE5MTIxOTQ4WhcNMjcwODE3MTIxOTQ4WjBVMQswCQYDVQQG | ||
EwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj | ||
bzEZMBcGA1UEAwwQVXNlcjFAaHJsLmlibS5pbDBZMBMGByqGSM49AgEGCCqGSM49 | ||
AwEHA0IABE7fF65KsF0nxNgIBFVA2x/QU0LuAyuTsRaSWc/ycQAuLQfCti5bYp4W | ||
WaQUc5sBaKAmVbFQTm9RhmOhtIz7PL6jTTBLMA4GA1UdDwEB/wQEAwIHgDAMBgNV | ||
HRMBAf8EAjAAMCsGA1UdIwQkMCKAIMjiBsyFZlbO6pRxo7VgoqKhl78Ujd9sdWUk | ||
epB05fodMAoGCCqGSM49BAMCA0gAMEUCIQCiOzbaApF46NVobwh3wqHf8ID1zxja | ||
j23HPXR3FjjFZgIgXLujyDGETptNrELaytjG+dxO3Kzq/SM07K2zPUg4368= | ||
-----END CERTIFICATE----- |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
-----BEGIN CERTIFICATE----- | ||
MIICGTCCAcCgAwIBAgIRAOazAZAhdFlzFdQYiWYwy3cwCgYIKoZIzj0EAwIwczEL | ||
MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG | ||
cmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh | ||
Lm9yZzEuZXhhbXBsZS5jb20wHhcNMTgwMTA3MTA0NDAzWhcNMTgwMTA3MTAzOTAz | ||
WjBbMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMN | ||
U2FuIEZyYW5jaXNjbzEfMB0GA1UEAwwWVXNlcjFAb3JnMS5leGFtcGxlLmNvbTBZ | ||
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABF6gDOVUGphkUaQj301wSXitdSpngXv8 | ||
Dee1b79s38WdZGrxL+7EOYxY1UhJBwKbNJqOvRcwSGRFkJthLpSSL32jTTBLMA4G | ||
A1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMCsGA1UdIwQkMCKAIC9+Pq7Gi7uv | ||
MCWUVvVIuOQPAqCWXT+5MYKe4Z+b2vy1MAoGCCqGSM49BAMCA0cAMEQCIBMh5fwh | ||
GFHAscjF04rVooiJ/o6tDrmPl8NBEbzdaNWoAiAe1/7LeS8DkQ+tfsBAoK/OECpu | ||
bDEvOYkljiKIpabYiQ== | ||
-----END CERTIFICATE----- |