Skip to content

Commit 7a26f1f

Browse files
committed
[FAB-5406] Mutual TLS in chaincode service-P3
This change set makes golang CC run on a different port (7052) and at startup of a chaincode container - generate a TLS certificate and pass it as commandline options to the shim container. The full details are in the JIRA item Change-Id: I6d274a235f2a66b310e61ee878ec4b881d6c8f49 Signed-off-by: yacovm <yacovm@il.ibm.com>
1 parent 47d0e3a commit 7a26f1f

File tree

10 files changed

+153
-92
lines changed

10 files changed

+153
-92
lines changed

core/chaincode/chaincode_support.go

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,13 @@ import (
2121
"io"
2222
"path/filepath"
2323
"strconv"
24+
"strings"
2425
"sync"
2526
"time"
2627

2728
"github.com/golang/protobuf/proto"
28-
logging "github.com/op/go-logging"
29-
"github.com/spf13/viper"
30-
"golang.org/x/net/context"
31-
32-
"strings"
33-
3429
"github.com/hyperledger/fabric/common/flogging"
30+
"github.com/hyperledger/fabric/core/chaincode/accesscontrol"
3531
"github.com/hyperledger/fabric/core/chaincode/platforms"
3632
"github.com/hyperledger/fabric/core/chaincode/shim"
3733
"github.com/hyperledger/fabric/core/common/ccprovider"
@@ -41,6 +37,9 @@ import (
4137
"github.com/hyperledger/fabric/core/container/ccintf"
4238
"github.com/hyperledger/fabric/core/ledger"
4339
pb "github.com/hyperledger/fabric/protos/peer"
40+
logging "github.com/op/go-logging"
41+
"github.com/spf13/viper"
42+
"golang.org/x/net/context"
4443
)
4544

4645
type key string
@@ -49,7 +48,7 @@ const (
4948
// DevModeUserRunsChaincode property allows user to run chaincode in development environment
5049
DevModeUserRunsChaincode string = "dev"
5150
chaincodeStartupTimeoutDefault int = 5000
52-
peerAddressDefault string = "0.0.0.0:7051"
51+
peerAddressDefault string = "0.0.0.0:7052"
5352

5453
//TXSimulatorKey is used to attach ledger simulation context
5554
TXSimulatorKey key = "txsimulatorkey"
@@ -132,38 +131,39 @@ func (chaincodeSupport *ChaincodeSupport) launchStarted(chaincode string) bool {
132131
}
133132

134133
// NewChaincodeSupport creates a new ChaincodeSupport instance
135-
func NewChaincodeSupport(getCCEndpoint func() (*pb.PeerEndpoint, error), userrunsCC bool, ccstartuptimeout time.Duration) *ChaincodeSupport {
134+
func NewChaincodeSupport(getCCEndpoint func() (*pb.PeerEndpoint, error), userrunsCC bool, ccstartuptimeout time.Duration, ca accesscontrol.CA) pb.ChaincodeSupportServer {
136135
ccprovider.SetChaincodesPath(config.GetPath("peer.fileSystemPath") + string(filepath.Separator) + "chaincodes")
137-
138136
pnid := viper.GetString("peer.networkId")
139137
pid := viper.GetString("peer.id")
140138

141-
theChaincodeSupport = &ChaincodeSupport{runningChaincodes: &runningChaincodes{chaincodeMap: make(map[string]*chaincodeRTEnv), launchStarted: make(map[string]bool)}, peerNetworkID: pnid, peerID: pid}
139+
theChaincodeSupport = &ChaincodeSupport{
140+
runningChaincodes: &runningChaincodes{
141+
chaincodeMap: make(map[string]*chaincodeRTEnv),
142+
launchStarted: make(map[string]bool),
143+
}, peerNetworkID: pnid, peerID: pid,
144+
}
142145

143-
//initialize global chain
146+
theChaincodeSupport.auth = accesscontrol.NewAuthenticator(theChaincodeSupport, ca)
144147

145148
ccEndpoint, err := getCCEndpoint()
146149
if err != nil {
147-
chaincodeLogger.Errorf("Error getting chaincode endpoint, using chaincode.peerAddress: %s", err)
148-
theChaincodeSupport.peerAddress = viper.GetString("chaincode.peerAddress")
150+
chaincodeLogger.Errorf("Error getting chaincode endpoint because %v, using %s", err, peerAddressDefault)
151+
theChaincodeSupport.peerAddress = peerAddressDefault
149152
} else {
150153
theChaincodeSupport.peerAddress = ccEndpoint.Address
151154
}
152155
chaincodeLogger.Infof("Chaincode support using peerAddress: %s\n", theChaincodeSupport.peerAddress)
153-
//peerAddress = viper.GetString("peer.address")
154-
if theChaincodeSupport.peerAddress == "" {
155-
theChaincodeSupport.peerAddress = peerAddressDefault
156-
}
157156

158157
theChaincodeSupport.userRunsCC = userrunsCC
159-
160158
theChaincodeSupport.ccStartupTimeout = ccstartuptimeout
161159

162160
theChaincodeSupport.peerTLS = viper.GetBool("peer.tls.enabled")
163161
if theChaincodeSupport.peerTLS {
164162
theChaincodeSupport.peerTLSCertFile = config.GetPath("peer.tls.cert.file")
165163
theChaincodeSupport.peerTLSKeyFile = config.GetPath("peer.tls.key.file")
166164
theChaincodeSupport.peerTLSSvrHostOrd = viper.GetString("peer.tls.serverhostoverride")
165+
} else {
166+
theChaincodeSupport.auth.DisableAccessCheck()
167167
}
168168

169169
kadef := 0
@@ -201,7 +201,7 @@ func NewChaincodeSupport(getCCEndpoint func() (*pb.PeerEndpoint, error), userrun
201201
theChaincodeSupport.shimLogLevel = getLogLevelFromViper("shim")
202202
theChaincodeSupport.logFormat = viper.GetString("chaincode.logging.format")
203203

204-
return theChaincodeSupport
204+
return theChaincodeSupport.auth
205205
}
206206

207207
// getLogLevelFromViper gets the chaincode container log levels from viper
@@ -226,6 +226,7 @@ func getLogLevelFromViper(module string) string {
226226

227227
// ChaincodeSupport responsible for providing interfacing with chaincodes from the Peer.
228228
type ChaincodeSupport struct {
229+
auth accesscontrol.Authenticator
229230
runningChaincodes *runningChaincodes
230231
peerAddress string
231232
ccStartupTimeout time.Duration
@@ -360,6 +361,13 @@ func (chaincodeSupport *ChaincodeSupport) sendReady(context context.Context, ccc
360361
return err
361362
}
362363

364+
func (chaincodeSupport *ChaincodeSupport) appendTLScerts(args []string, keyPair *accesscontrol.CertAndPrivKeyPair) []string {
365+
if keyPair == nil {
366+
return args
367+
}
368+
return append(args, []string{"--key", keyPair.Key, "--cert", keyPair.Cert}...)
369+
}
370+
363371
//get args and env given chaincodeID
364372
func (chaincodeSupport *ChaincodeSupport) getArgsAndEnv(cccid *ccprovider.CCContext, cLang pb.ChaincodeSpec_Type) (args []string, envs []string, err error) {
365373
canName := cccid.GetCanonicalName()
@@ -375,7 +383,12 @@ func (chaincodeSupport *ChaincodeSupport) getArgsAndEnv(cccid *ccprovider.CCCont
375383
// the image may be stale and the admin will need to remove the current containers
376384
// before restarting the peer.
377385
// ----------------------------------------------------------------------------
386+
var certKeyPair *accesscontrol.CertAndPrivKeyPair
378387
if chaincodeSupport.peerTLS {
388+
certKeyPair, err = chaincodeSupport.auth.Generate(cccid.GetCanonicalName())
389+
if err != nil {
390+
return nil, nil, fmt.Errorf("failed generating TLS cert for %s: %v", cccid.GetCanonicalName(), err)
391+
}
379392
envs = append(envs, "CORE_PEER_TLS_ENABLED=true")
380393
if chaincodeSupport.peerTLSSvrHostOrd != "" {
381394
envs = append(envs, "CORE_PEER_TLS_SERVERHOSTOVERRIDE="+chaincodeSupport.peerTLSSvrHostOrd)
@@ -398,6 +411,7 @@ func (chaincodeSupport *ChaincodeSupport) getArgsAndEnv(cccid *ccprovider.CCCont
398411
switch cLang {
399412
case pb.ChaincodeSpec_GOLANG, pb.ChaincodeSpec_CAR:
400413
args = []string{"chaincode", fmt.Sprintf("-peer.address=%s", chaincodeSupport.peerAddress)}
414+
args = theChaincodeSupport.appendTLScerts(args, certKeyPair)
401415
case pb.ChaincodeSpec_JAVA:
402416
args = []string{"java", "-jar", "chaincode.jar", "--peerAddress", chaincodeSupport.peerAddress}
403417
default:

core/chaincode/chaincode_support_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
mocklgr "github.com/hyperledger/fabric/common/mocks/ledger"
3434
mockpeer "github.com/hyperledger/fabric/common/mocks/peer"
3535
"github.com/hyperledger/fabric/common/util"
36+
"github.com/hyperledger/fabric/core/chaincode/accesscontrol"
3637
"github.com/hyperledger/fabric/core/chaincode/shim"
3738
"github.com/hyperledger/fabric/core/common/ccprovider"
3839
"github.com/hyperledger/fabric/core/config"
@@ -152,7 +153,8 @@ func initMockPeer(chainIDs ...string) error {
152153
}
153154

154155
ccStartupTimeout := time.Duration(2) * time.Second
155-
NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout)
156+
ca, _ := accesscontrol.NewCA()
157+
NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout, ca)
156158
theChaincodeSupport.executetimeout = time.Duration(1) * time.Second
157159

158160
// Mock policy checker

core/chaincode/exectransaction_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
mockpolicies "github.com/hyperledger/fabric/common/mocks/policies"
3939
"github.com/hyperledger/fabric/common/policies"
4040
"github.com/hyperledger/fabric/common/util"
41+
"github.com/hyperledger/fabric/core/chaincode/accesscontrol"
4142
"github.com/hyperledger/fabric/core/common/ccprovider"
4243
"github.com/hyperledger/fabric/core/config"
4344
"github.com/hyperledger/fabric/core/container"
@@ -109,7 +110,8 @@ func initPeer(chainIDs ...string) (net.Listener, error) {
109110
}
110111

111112
ccStartupTimeout := time.Duration(chaincodeStartupTimeoutDefault) * time.Millisecond
112-
pb.RegisterChaincodeSupportServer(grpcServer, NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout))
113+
ca, _ := accesscontrol.NewCA()
114+
pb.RegisterChaincodeSupportServer(grpcServer, NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout, ca))
113115

114116
// Mock policy checker
115117
policy.RegisterPolicyCheckerFactory(&mockPolicyCheckerFactory{})

core/chaincode/shim/chaincode.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ import (
4646
var chaincodeLogger = logging.MustGetLogger("shim")
4747
var logOutput = os.Stderr
4848

49+
var key string
50+
var cert string
51+
4952
const (
5053
minUnicodeRuneValue = 0 //U+0000
5154
maxUnicodeRuneValue = utf8.MaxRune //U+10FFFF - maximum (and unallocated) code point
@@ -84,6 +87,10 @@ var streamGetter peerStreamGetter
8487
//the non-mock user CC stream establishment func
8588
func userChaincodeStreamGetter(name string) (PeerChaincodeStream, error) {
8689
flag.StringVar(&peerAddress, "peer.address", "", "peer address")
90+
if comm.TLSEnabled() {
91+
flag.StringVar(&key, "key", "", "key in BASE64")
92+
flag.StringVar(&cert, "cert", "", "certificate in BASE64")
93+
}
8794

8895
flag.Parse()
8996

@@ -233,7 +240,7 @@ func getPeerAddress() string {
233240
func newPeerClientConnection() (*grpc.ClientConn, error) {
234241
var peerAddress = getPeerAddress()
235242
if comm.TLSEnabled() {
236-
return comm.NewClientConnectionWithAddress(peerAddress, true, true, comm.InitTLSForPeer())
243+
return comm.NewClientConnectionWithAddress(peerAddress, true, true, comm.InitTLSForShim(key, cert))
237244
}
238245
return comm.NewClientConnectionWithAddress(peerAddress, true, false, nil)
239246
}

core/chaincode/systemchaincode_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"time"
2424

2525
"github.com/hyperledger/fabric/common/util"
26+
"github.com/hyperledger/fabric/core/chaincode/accesscontrol"
2627
"github.com/hyperledger/fabric/core/common/ccprovider"
2728
"github.com/hyperledger/fabric/core/peer"
2829
"github.com/hyperledger/fabric/core/scc"
@@ -71,7 +72,8 @@ func initSysCCTests() (*oldSysCCInfo, net.Listener, error) {
7172
}
7273

7374
ccStartupTimeout := time.Duration(5000) * time.Millisecond
74-
pb.RegisterChaincodeSupportServer(grpcServer, NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout))
75+
ca, _ := accesscontrol.NewCA()
76+
pb.RegisterChaincodeSupportServer(grpcServer, NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout, ca))
7577

7678
go grpcServer.Serve(lis)
7779

core/comm/connection.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@ package comm
99
import (
1010
"crypto/tls"
1111
"crypto/x509"
12+
"encoding/base64"
1213
"encoding/pem"
14+
"errors"
1315
"fmt"
16+
"io/ioutil"
1417
"os"
1518
"sync"
1619
"time"
@@ -213,3 +216,35 @@ func InitTLSForPeer() credentials.TransportCredentials {
213216
}
214217
return creds
215218
}
219+
220+
func InitTLSForShim(key, certStr string) credentials.TransportCredentials {
221+
var sn string
222+
if viper.GetString("peer.tls.serverhostoverride") != "" {
223+
sn = viper.GetString("peer.tls.serverhostoverride")
224+
}
225+
priv, err := base64.StdEncoding.DecodeString(key)
226+
if err != nil {
227+
panic(fmt.Errorf("failed decoding private key from base64, string: %s, error: %v", key, err))
228+
}
229+
pub, err := base64.StdEncoding.DecodeString(certStr)
230+
if err != nil {
231+
panic(fmt.Errorf("failed decoding public key from base64, string: %s, error: %v", certStr, err))
232+
}
233+
cert, err := tls.X509KeyPair(pub, priv)
234+
if err != nil {
235+
panic(fmt.Errorf("failed loading certificate: %v", err))
236+
}
237+
b, err := ioutil.ReadFile(config.GetPath("peer.tls.rootcert.file"))
238+
if err != nil {
239+
panic(fmt.Errorf("failed loading root ca cert: %v", err))
240+
}
241+
cp := x509.NewCertPool()
242+
if !cp.AppendCertsFromPEM(b) {
243+
panic(errors.New("failed to append certificates"))
244+
}
245+
return credentials.NewTLS(&tls.Config{
246+
Certificates: []tls.Certificate{cert},
247+
RootCAs: cp,
248+
ServerName: sn,
249+
})
250+
}

core/endorser/endorser_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"github.com/hyperledger/fabric/common/policies"
3838
"github.com/hyperledger/fabric/common/util"
3939
"github.com/hyperledger/fabric/core/chaincode"
40+
"github.com/hyperledger/fabric/core/chaincode/accesscontrol"
4041
"github.com/hyperledger/fabric/core/common/ccprovider"
4142
"github.com/hyperledger/fabric/core/config"
4243
"github.com/hyperledger/fabric/core/container"
@@ -104,7 +105,8 @@ func initPeer(chainID string) (*testEnvironment, error) {
104105
}
105106

106107
ccStartupTimeout := time.Duration(30000) * time.Millisecond
107-
pb.RegisterChaincodeSupportServer(grpcServer, chaincode.NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout))
108+
ca, _ := accesscontrol.NewCA()
109+
pb.RegisterChaincodeSupportServer(grpcServer, chaincode.NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout, ca))
108110

109111
syscc.RegisterSysCCs()
110112

core/scc/cscc/configure_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/hyperledger/fabric/common/mocks/scc"
3030
"github.com/hyperledger/fabric/common/policies"
3131
"github.com/hyperledger/fabric/core/chaincode"
32+
"github.com/hyperledger/fabric/core/chaincode/accesscontrol"
3233
"github.com/hyperledger/fabric/core/chaincode/shim"
3334
"github.com/hyperledger/fabric/core/common/sysccprovider"
3435
"github.com/hyperledger/fabric/core/deliverservice"
@@ -180,7 +181,8 @@ func TestConfigerInvokeJoinChainCorrectParams(t *testing.T) {
180181
return &pb.PeerEndpoint{Id: &pb.PeerID{Name: "cscctestpeer"}, Address: peerEndpoint}, nil
181182
}
182183
ccStartupTimeout := time.Duration(30000) * time.Millisecond
183-
chaincode.NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout)
184+
ca, _ := accesscontrol.NewCA()
185+
chaincode.NewChaincodeSupport(getPeerEndpoint, false, ccStartupTimeout, ca)
184186

185187
// Init the policy checker
186188
policyManagerGetter := &policymocks.MockChannelPolicyManagerGetter{

0 commit comments

Comments
 (0)