Skip to content

Commit 08e65db

Browse files
committed
add consnter info to router config
add router info to consenter config router's certificate pinning in SubmitConfig add configSubmitter to router, without forwarding config requests Signed-off-by: Dor.Katzelnick <Dor.Katzelnick@ibm.com>
1 parent efa9485 commit 08e65db

File tree

11 files changed

+165
-128
lines changed

11 files changed

+165
-128
lines changed

common/utils/pem_utils.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package utils
8+
9+
import (
10+
"crypto/ecdsa"
11+
"crypto/x509"
12+
"encoding/pem"
13+
"fmt"
14+
"os"
15+
)
16+
17+
func ReadPem(path string) ([]byte, error) {
18+
if path == "" {
19+
return nil, fmt.Errorf("failed reading pem file, path is empty")
20+
}
21+
data, err := os.ReadFile(path)
22+
if err != nil {
23+
return nil, fmt.Errorf("failed reading a pem file from %s, err: %v", path, err)
24+
}
25+
26+
return data, nil
27+
}
28+
29+
func blockToPublicKey(block *pem.Block) []byte {
30+
cert, err := x509.ParseCertificate(block.Bytes)
31+
if err != nil {
32+
panic(fmt.Sprintf("Failed parsing consenter signing certificate: %v", err))
33+
}
34+
35+
pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
36+
if !ok {
37+
panic(fmt.Sprintf("Failed parsing consenter public key: %v", err))
38+
}
39+
40+
publicKeyBytes, err := x509.MarshalPKIXPublicKey(pubKey)
41+
if err != nil {
42+
panic(fmt.Sprintf("Failed marshaling consenter public key: %v", err))
43+
}
44+
45+
pemPublicKey := pem.EncodeToMemory(&pem.Block{
46+
Type: "PUBLIC KEY",
47+
Bytes: publicKeyBytes,
48+
})
49+
50+
return pemPublicKey
51+
}
52+
53+
func GetPublicKeyFromCertificate(nodeCert []byte) []byte {
54+
// Fetch public key from signing certificate
55+
// NOTE: ARMA's new configuration now uses certificates, which inherently contain the public key, instead of a separate public key field.
56+
// To ensure backward compatibility until the full new config integration, the public key it enabled.
57+
block, _ := pem.Decode(nodeCert)
58+
if block == nil || block.Bytes == nil {
59+
panic("Failed decoding consenter signing certificate")
60+
}
61+
62+
var pemPublicKey []byte
63+
if block.Type == "CERTIFICATE" {
64+
pemPublicKey = blockToPublicKey(block)
65+
}
66+
67+
if block.Type == "PUBLIC KEY" {
68+
pemPublicKey = nodeCert
69+
}
70+
71+
return pemPublicKey
72+
}
File renamed without changes.

common/utils/read_pem.go

Lines changed: 0 additions & 24 deletions
This file was deleted.

config/config.go

Lines changed: 22 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@ SPDX-License-Identifier: Apache-2.0
77
package config
88

99
import (
10-
"crypto/ecdsa"
11-
"crypto/x509"
12-
"encoding/pem"
1310
"fmt"
1411
"os"
1512
"path/filepath"
@@ -249,6 +246,7 @@ func (config *Configuration) ExtractRouterConfig(configBlock *common.Block) *nod
249246
ListenAddress: config.LocalConfig.NodeLocalConfig.GeneralConfig.ListenAddress + ":" + strconv.Itoa(int(config.LocalConfig.NodeLocalConfig.GeneralConfig.ListenPort)),
250247
ConfigStorePath: config.LocalConfig.NodeLocalConfig.FileStore.Path,
251248
Shards: config.ExtractShards(),
249+
Consenter: config.ExtractConsenterInParty(),
252250
NumOfConnectionsForBatcher: config.LocalConfig.NodeLocalConfig.RouterParams.NumberOfConnectionsPerBatcher,
253251
NumOfgRPCStreamsPerConnection: config.LocalConfig.NodeLocalConfig.RouterParams.NumberOfStreamsPerConnection,
254252
UseTLS: config.LocalConfig.TLSConfig.Enabled,
@@ -318,6 +316,7 @@ func (config *Configuration) ExtractConsenterConfig() *nodeconfig.ConsenterNodeC
318316
consenterConfig := &nodeconfig.ConsenterNodeConfig{
319317
Shards: config.ExtractShards(),
320318
Consenters: config.ExtractConsenters(),
319+
Router: config.ExtractRouterInParty(),
321320
Directory: config.LocalConfig.NodeLocalConfig.FileStore.Path,
322321
ListenAddress: config.LocalConfig.NodeLocalConfig.GeneralConfig.ListenAddress + ":" + strconv.Itoa(int(config.LocalConfig.NodeLocalConfig.GeneralConfig.ListenPort)),
323322
PartyId: config.LocalConfig.NodeLocalConfig.PartyID,
@@ -372,22 +371,7 @@ func (config *Configuration) ExtractShards() []nodeconfig.ShardInfo {
372371
for _, batcher := range party.BatchersConfig {
373372
shardId := types.ShardID(batcher.ShardID)
374373

375-
// Fetch public key from signing certificate
376-
// NOTE: ARMA's new configuration uses certificates, which inherently contain the public key, instead of a separate public key field.
377-
// To ensure backward compatibility until the full new config integration, the public key it enabled.
378-
block, _ := pem.Decode(batcher.SignCert)
379-
if block == nil || block.Bytes == nil {
380-
panic("Failed decoding batcher signing certificate")
381-
}
382-
383-
var pemPublicKey []byte
384-
if block.Type == "CERTIFICATE" {
385-
pemPublicKey = blockToPublicKey(block)
386-
}
387-
388-
if block.Type == "PUBLIC KEY" {
389-
pemPublicKey = batcher.SignCert
390-
}
374+
pemPublicKey := utils.GetPublicKeyFromCertificate(batcher.SignCert)
391375

392376
batcher := nodeconfig.BatcherInfo{
393377
PartyID: types.PartyID(party.PartyID),
@@ -425,22 +409,7 @@ func (config *Configuration) ExtractConsenters() []nodeconfig.ConsenterInfo {
425409
tlsCACertsCollection = append(tlsCACertsCollection, ca)
426410
}
427411

428-
// Fetch public key from signing certificate
429-
// NOTE: ARMA's new configuration now uses certificates, which inherently contain the public key, instead of a separate public key field.
430-
// To ensure backward compatibility until the full new config integration, the public key it enabled.
431-
block, _ := pem.Decode(party.ConsenterConfig.SignCert)
432-
if block == nil || block.Bytes == nil {
433-
panic("Failed decoding consenter signing certificate")
434-
}
435-
436-
var pemPublicKey []byte
437-
if block.Type == "CERTIFICATE" {
438-
pemPublicKey = blockToPublicKey(block)
439-
}
440-
441-
if block.Type == "PUBLIC KEY" {
442-
pemPublicKey = party.ConsenterConfig.SignCert
443-
}
412+
pemPublicKey := utils.GetPublicKeyFromCertificate(party.ConsenterConfig.SignCert)
444413

445414
consenterInfo := nodeconfig.ConsenterInfo{
446415
PartyID: types.PartyID(party.PartyID),
@@ -454,26 +423,28 @@ func (config *Configuration) ExtractConsenters() []nodeconfig.ConsenterInfo {
454423
return consenters
455424
}
456425

457-
func blockToPublicKey(block *pem.Block) []byte {
458-
cert, err := x509.ParseCertificate(block.Bytes)
459-
if err != nil {
460-
panic(fmt.Sprintf("Failed parsing consenter signing certificate: %v", err))
461-
}
426+
func (config *Configuration) ExtractRouterInParty() nodeconfig.RouterInfo {
427+
partyID := config.LocalConfig.NodeLocalConfig.PartyID
428+
party := config.SharedConfig.PartiesConfig[partyID-1]
429+
routerConfig := party.RouterConfig
462430

463-
pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
464-
if !ok {
465-
panic(fmt.Sprintf("Failed parsing consenter public key: %v", err))
431+
var tlsCACertsCollection []nodeconfig.RawBytes
432+
for _, ca := range party.TLSCACerts {
433+
tlsCACertsCollection = append(tlsCACertsCollection, ca)
466434
}
467435

468-
publicKeyBytes, err := x509.MarshalPKIXPublicKey(pubKey)
469-
if err != nil {
470-
panic(fmt.Sprintf("Failed marshaling consenter public key: %v", err))
436+
routerInfo := nodeconfig.RouterInfo{
437+
PartyID: partyID,
438+
Endpoint: routerConfig.Host + ":" + strconv.Itoa(int(routerConfig.Port)),
439+
TLSCACerts: tlsCACertsCollection,
440+
TLSCert: routerConfig.TlsCert,
471441
}
472442

473-
pemPublicKey := pem.EncodeToMemory(&pem.Block{
474-
Type: "PUBLIC KEY",
475-
Bytes: publicKeyBytes,
476-
})
443+
return routerInfo
444+
}
477445

478-
return pemPublicKey
446+
func (config *Configuration) ExtractConsenterInParty() nodeconfig.ConsenterInfo {
447+
partyID := config.LocalConfig.NodeLocalConfig.PartyID
448+
consenterInfos := config.ExtractConsenters()
449+
return consenterInfos[partyID-1]
479450
}

node/config/config.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ type ConsenterInfo struct {
6565
TLSCACerts []RawBytes
6666
}
6767

68+
type RouterInfo struct {
69+
PartyID types.PartyID
70+
Endpoint string
71+
TLSCACerts []RawBytes
72+
TLSCert RawBytes
73+
}
74+
6875
type RouterNodeConfig struct {
6976
// Private config
7077
PartyID types.PartyID
@@ -74,6 +81,7 @@ type RouterNodeConfig struct {
7481
ConfigStorePath string
7582
// Shared config
7683
Shards []ShardInfo
84+
Consenter ConsenterInfo
7785
NumOfConnectionsForBatcher int
7886
NumOfgRPCStreamsPerConnection int
7987
UseTLS bool
@@ -134,6 +142,7 @@ type ConsenterNodeConfig struct {
134142
// Shared config
135143
Shards []ShardInfo
136144
Consenters []ConsenterInfo
145+
Router RouterInfo
137146
Directory string
138147
ListenAddress string
139148
// Private config

node/config/config_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,15 @@ func TestRouterNodeConfigToYaml(t *testing.T) {
2525
{2, "127.0.0.1:7051", []RawBytes{{1, 2, 3}, {4, 5, 6}}, RawBytes("BatcherPubKey-2"), RawBytes("TLS CERT")},
2626
}
2727

28+
consenter := ConsenterInfo{1, "127.0.0.1:7050", RawBytes("ConsenterPubKey-1"), []RawBytes{{1, 2, 3}, {4, 5, 6}}}
29+
2830
shards := []ShardInfo{{ShardId: 1, Batchers: batchers}}
2931
rnc := &RouterNodeConfig{
3032
TLSCertificateFile: []byte("tls cert"),
3133
TLSPrivateKeyFile: []byte("tls key"),
3234
PartyID: 1,
3335
Shards: shards,
36+
Consenter: consenter,
3437
NumOfConnectionsForBatcher: 1,
3538
NumOfgRPCStreamsPerConnection: 2,
3639
}
@@ -87,10 +90,12 @@ func TestConsenterNodeConfigToYaml(t *testing.T) {
8790
}
8891
shards := []ShardInfo{{ShardId: 1, Batchers: batchers}}
8992
consenters := []ConsenterInfo{{1, "127.0.0.1:7050", RawBytes("ConsenterPubKey-1"), []RawBytes{{1, 2, 3}, {4, 5, 6}}}}
93+
router := RouterInfo{1, "127.0.0.1:7050", []RawBytes{{1, 2, 3}, {4, 5, 6}}, RawBytes("ConsenterPubKey-1")}
9094

9195
cnc := &ConsenterNodeConfig{
9296
Shards: shards,
9397
Consenters: consenters,
98+
Router: router,
9499
PartyId: 1,
95100
TLSPrivateKeyFile: RawBytes("TlsPrivateKey"),
96101
TLSCertificateFile: RawBytes("TlsCertKey"),

node/consensus/consensus.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"encoding/asn1"
1313
"encoding/base64"
1414
"encoding/hex"
15+
"encoding/pem"
1516
"fmt"
1617
"io"
1718
"math/rand"
@@ -23,6 +24,7 @@ import (
2324
"github.com/hyperledger/fabric-protos-go-apiv2/common"
2425
"github.com/hyperledger/fabric-protos-go-apiv2/orderer"
2526
arma_types "github.com/hyperledger/fabric-x-orderer/common/types"
27+
"github.com/hyperledger/fabric-x-orderer/node"
2628
"github.com/hyperledger/fabric-x-orderer/node/comm"
2729
"github.com/hyperledger/fabric-x-orderer/node/config"
2830
"github.com/hyperledger/fabric-x-orderer/node/consensus/badb"
@@ -141,9 +143,15 @@ func (c *Consensus) NotifyEvent(stream protos.Consensus_NotifyEventServer) error
141143
}
142144

143145
// SubmitConfig is used to submit a config request from the router in the consenter's party.
144-
// TODO - add certificate pinning of the router, and forward the request.
145-
func (sc *Consensus) SubmitConfig(ctx context.Context, request *protos.Request) (*protos.SubmitResponse, error) {
146-
return nil, fmt.Errorf("SubmitConfig not implemented")
146+
func (c *Consensus) SubmitConfig(ctx context.Context, request *protos.Request) (*protos.SubmitResponse, error) {
147+
err := c.validateRouterFromContext(ctx)
148+
if err != nil {
149+
return nil, err
150+
}
151+
152+
c.Logger.Infof("Received config request from router %s", c.Config.Router.Endpoint)
153+
154+
return &protos.SubmitResponse{Error: "SubmitConfig is not implemented in consenter", TraceId: request.TraceId}, nil
147155
}
148156

149157
func (c *Consensus) SubmitRequest(req []byte) error {
@@ -559,3 +567,24 @@ func (c *Consensus) verifyCE(req []byte) (smartbft_types.RequestInfo, *state.Con
559567
return smartbft_types.RequestInfo{}, ce, fmt.Errorf("empty control event")
560568
}
561569
}
570+
571+
func (c *Consensus) validateRouterFromContext(ctx context.Context) error {
572+
// extract the client certificate from the context
573+
cert := node.ExtractCertificateFromContext(ctx)
574+
if cert == nil {
575+
return errors.New("error: access denied; could not extract certificate from context")
576+
}
577+
578+
// extract the router certificate from the ConsenterNodeConfig
579+
rawRouterCert := c.Config.Router.TLSCert
580+
pemBlock, _ := pem.Decode(rawRouterCert)
581+
if pemBlock == nil || pemBlock.Bytes == nil {
582+
return fmt.Errorf("error decoding router TLS certificate")
583+
}
584+
585+
// compare the two certificates
586+
if !bytes.Equal(pemBlock.Bytes, cert.Raw) {
587+
return fmt.Errorf("error: access denied; client certificatte is different than the router's certificate")
588+
}
589+
return nil
590+
}

0 commit comments

Comments
 (0)