Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

External chaincode clients and servers should use consistent key/cert model #407

Merged
merged 1 commit into from
Dec 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 18 additions & 31 deletions core/container/externalbuilder/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package externalbuilder

import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"os/exec"
Expand Down Expand Up @@ -69,63 +68,51 @@ func (d *Duration) UnmarshalJSON(b []byte) error {
type ChaincodeServerUserData struct {
Address string `json:"address"`
DialTimeout Duration `json:"dial_timeout"`
TlsRequired bool `json:"tls_required"`
TLSRequired bool `json:"tls_required"`
ClientAuthRequired bool `json:"client_auth_required"`
KeyPath string `json:"key_path"`
CertPath string `json:"cert_path"`
RootCertPath string `json:"root_cert_path"`
ClientKey string `json:"client_key"` // PEM encoded client key
ClientCert string `json:"client_cert"` // PEM encoded client certificate
RootCert string `json:"root_cert"` // PEM encoded peer chaincode certificate

}

func (ccdata *ChaincodeServerUserData) ChaincodeServerInfo(cryptoDir string) (*ccintf.ChaincodeServerInfo, error) {
if ccdata.Address == "" {
func (c *ChaincodeServerUserData) ChaincodeServerInfo(cryptoDir string) (*ccintf.ChaincodeServerInfo, error) {
if c.Address == "" {
return nil, errors.New("chaincode address not provided")
}
connInfo := &ccintf.ChaincodeServerInfo{Address: ccdata.Address}
connInfo := &ccintf.ChaincodeServerInfo{Address: c.Address}

if ccdata.DialTimeout == (Duration{}) {
if c.DialTimeout == (Duration{}) {
connInfo.ClientConfig.Timeout = DialTimeout
} else {
connInfo.ClientConfig.Timeout = ccdata.DialTimeout.Duration
connInfo.ClientConfig.Timeout = c.DialTimeout.Duration
}

// we can expose this if necessary
connInfo.ClientConfig.KaOpts = comm.DefaultKeepaliveOptions

if !ccdata.TlsRequired {
if !c.TLSRequired {
return connInfo, nil
}
if ccdata.ClientAuthRequired && ccdata.KeyPath == "" {
if c.ClientAuthRequired && c.ClientKey == "" {
return nil, errors.New("chaincode tls key not provided")
}
if ccdata.ClientAuthRequired && ccdata.CertPath == "" {
if c.ClientAuthRequired && c.ClientCert == "" {
return nil, errors.New("chaincode tls cert not provided")
}
if ccdata.RootCertPath == "" {
if c.RootCert == "" {
return nil, errors.New("chaincode tls root cert not provided")
}

connInfo.ClientConfig.SecOpts.UseTLS = true

if ccdata.ClientAuthRequired {
if c.ClientAuthRequired {
connInfo.ClientConfig.SecOpts.RequireClientCert = true
b, err := ioutil.ReadFile(filepath.Join(cryptoDir, ccdata.CertPath))
if err != nil {
return nil, errors.WithMessage(err, fmt.Sprintf("error reading cert file %s", ccdata.CertPath))
}
connInfo.ClientConfig.SecOpts.Certificate = b

b, err = ioutil.ReadFile(filepath.Join(cryptoDir, ccdata.KeyPath))
if err != nil {
return nil, errors.WithMessage(err, fmt.Sprintf("error reading key file %s", ccdata.KeyPath))
}
connInfo.ClientConfig.SecOpts.Key = b
connInfo.ClientConfig.SecOpts.Certificate = []byte(c.ClientCert)
connInfo.ClientConfig.SecOpts.Key = []byte(c.ClientKey)
}

b, err := ioutil.ReadFile(filepath.Join(cryptoDir, ccdata.RootCertPath))
if err != nil {
return nil, errors.WithMessage(err, fmt.Sprintf("error reading root cert file %s", ccdata.RootCertPath))
}
connInfo.ClientConfig.SecOpts.ServerRootCAs = [][]byte{b}
connInfo.ClientConfig.SecOpts.ServerRootCAs = [][]byte{[]byte(c.RootCert)}

return connInfo, nil
}
Expand Down
77 changes: 18 additions & 59 deletions core/container/externalbuilder/instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,10 @@ var _ = Describe("Instance", func() {

err = os.MkdirAll(filepath.Join(instance.ReleaseDir, "chaincode", "server"), 0755)
Expect(err).NotTo(HaveOccurred())
//initiaze with a well-formed, all fields set, connection.json file
ccdata := `{"address": "ccaddress:12345", "tls_required": true, "dial_timeout": "10s", "client_auth_required": true, "key_path": "key.pem", "cert_path": "cert.pem", "root_cert_path": "root.pem"}`
// initialize with a well-formed, all fields set, connection.json file
ccdata := `{"address": "ccaddress:12345", "tls_required": true, "dial_timeout": "10s", "client_auth_required": true, "client_key": "fake-key", "client_cert": "fake-cert", "root_cert": "fake-root-cert"}`
err = ioutil.WriteFile(filepath.Join(instance.ChaincodeServerReleaseDir(), "connection.json"), []byte(ccdata), 0600)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(instance.ChaincodeServerReleaseDir(), "key.pem"), []byte("fake-key"), 0600)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(instance.ChaincodeServerReleaseDir(), "cert.pem"), []byte("fake-cert"), 0600)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(instance.ChaincodeServerReleaseDir(), "root.pem"), []byte("fake-root-cert"), 0600)
Expect(err).NotTo(HaveOccurred())
})

AfterEach(func() {
Expand Down Expand Up @@ -127,31 +121,26 @@ var _ = Describe("Instance", func() {

err = os.MkdirAll(filepath.Join(releaseDir, "chaincode", "server"), 0755)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(releaseDir, "key.pem"), []byte("fake-key"), 0600)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(releaseDir, "cert.pem"), []byte("fake-cert"), 0600)
Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(releaseDir, "root.pem"), []byte("fake-root-cert"), 0600)
Expect(err).NotTo(HaveOccurred())

ccuserdata = &externalbuilder.ChaincodeServerUserData{
Address: "ccaddress:12345",
DialTimeout: externalbuilder.Duration{10 * time.Second},
TlsRequired: true,
TLSRequired: true,
ClientAuthRequired: true,
KeyPath: "key.pem",
CertPath: "cert.pem",
RootCertPath: "root.pem",
ClientKey: "fake-key",
ClientCert: "fake-cert",
RootCert: "fake-root-cert",
}
})

AfterEach(func() {
os.RemoveAll(releaseDir)
})

When("chaincode does not provide all info", func() {
Context("tls is not provided", func() {
It("returns TLS without client auth information", func() {
//"tls" missing
ccuserdata.TlsRequired = false
ccuserdata.TLSRequired = false

ccinfo, err := ccuserdata.ChaincodeServerInfo(releaseDir)
Expect(err).NotTo(HaveOccurred())
Expand All @@ -164,9 +153,9 @@ var _ = Describe("Instance", func() {
}))
})
})

Context("client auth is not provided", func() {
It("returns TLS without client auth information", func() {
//"client_auth_required" missing
ccuserdata.ClientAuthRequired = false

ccinfo, err := ccuserdata.ChaincodeServerInfo(releaseDir)
Expand All @@ -184,9 +173,9 @@ var _ = Describe("Instance", func() {
}))
})
})

Context("dial timeout not provided", func() {
It("returns default dial timeout without dialtimeout", func() {
//"dial_timeout" missing
ccuserdata.DialTimeout = externalbuilder.Duration{}

ccinfo, err := ccuserdata.ChaincodeServerInfo(releaseDir)
Expand All @@ -207,72 +196,42 @@ var _ = Describe("Instance", func() {
}))
})
})

Context("address is not provided", func() {
It("returns missing address error", func() {
//"address" missing
ccuserdata.Address = ""

_, err := ccuserdata.ChaincodeServerInfo(releaseDir)
Expect(err).To(MatchError("chaincode address not provided"))
})
})

Context("key is not provided", func() {
It("returns missing key error", func() {
//"key" missing
ccuserdata.KeyPath = ""
ccuserdata.ClientKey = ""

_, err := ccuserdata.ChaincodeServerInfo(releaseDir)
Expect(err).To(MatchError("chaincode tls key not provided"))
})
})

Context("cert is not provided", func() {
It("returns missing key error", func() {
//"cert" missing
ccuserdata.CertPath = ""
ccuserdata.ClientCert = ""

_, err := ccuserdata.ChaincodeServerInfo(releaseDir)
Expect(err).To(MatchError("chaincode tls cert not provided"))
})
})

Context("root cert is not provided", func() {
It("returns missing root cert error", func() {
//"root" missing
ccuserdata.RootCertPath = ""
ccuserdata.RootCert = ""

_, err := ccuserdata.ChaincodeServerInfo(releaseDir)
Expect(err).To(MatchError("chaincode tls root cert not provided"))
})
})
Context("cert file is missing", func() {
It("returns missing cert file error", func() {
//cert file is missing
err := os.Remove(filepath.Join(releaseDir, "cert.pem"))
Expect(err).NotTo(HaveOccurred())

_, err = ccuserdata.ChaincodeServerInfo(releaseDir)
Expect(err).To(MatchError(ContainSubstring("error reading cert file")))
})
})
Context("key file is missing", func() {
It("returns missing key file error", func() {
//key file is missing
err := os.Remove(filepath.Join(releaseDir, "key.pem"))
Expect(err).NotTo(HaveOccurred())

_, err = ccuserdata.ChaincodeServerInfo(releaseDir)
Expect(err).To(MatchError(ContainSubstring("error reading key file")))
})
})
Context("root cert file is missing", func() {
It("returns missing root cert file error", func() {
//key file is missing
err := os.Remove(filepath.Join(releaseDir, "root.pem"))
Expect(err).NotTo(HaveOccurred())

_, err = ccuserdata.ChaincodeServerInfo(releaseDir)
Expect(err).To(MatchError(ContainSubstring("error reading root cert file")))
})
})
})
})

Expand Down