Skip to content

Commit

Permalink
FAB-17057 Generate crypto during orderer/common/server UT (#373)
Browse files Browse the repository at this point in the history
Change-Id: Iff7cf5eac5403ff19057d48e452eb18200e2d0eb
Signed-off-by: Will Lahti <[email protected]>
  • Loading branch information
wlahti authored and yacovm committed Dec 7, 2019
1 parent c3720b4 commit f5799c0
Show file tree
Hide file tree
Showing 11 changed files with 503 additions and 173 deletions.
132 changes: 76 additions & 56 deletions orderer/common/server/etcdraft_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,56 +38,64 @@ func TestSpawnEtcdRaft(t *testing.T) {
configtxgen, err := gexec.Build("github.com/hyperledger/fabric/cmd/configtxgen")
gt.Expect(err).NotTo(HaveOccurred())

cryptogen, err := gexec.Build("github.com/hyperledger/fabric/cmd/cryptogen")
gt.Expect(err).NotTo(HaveOccurred())

// Build the orderer binary
orderer, err := gexec.Build("github.com/hyperledger/fabric/cmd/orderer")
gt.Expect(err).NotTo(HaveOccurred())

defer gexec.CleanupBuildArtifacts()

t.Run("Bad", func(t *testing.T) {
gt = NewGomegaWithT(t)
tempDir, err := ioutil.TempDir("", "etcdraft-orderer-launch")
gt.Expect(err).NotTo(HaveOccurred())
defer os.RemoveAll(tempDir)
tempDir, err := ioutil.TempDir("", "etcdraft-test")
defer os.RemoveAll(tempDir)

copyYamlFiles(gt, "testdata", tempDir)

cryptoPath := generateCryptoMaterials(gt, cryptogen, tempDir)

t.Run("Bad", func(t *testing.T) {
t.Run("Invalid bootstrap block", func(t *testing.T) {
testEtcdRaftOSNFailureInvalidBootstrapBlock(NewGomegaWithT(t), tempDir, orderer, fabricRootDir, configtxgen)
testEtcdRaftOSNFailureInvalidBootstrapBlock(NewGomegaWithT(t), tempDir, orderer, fabricRootDir, configtxgen, cryptoPath)
})

t.Run("TLS disabled single listener", func(t *testing.T) {
testEtcdRaftOSNNoTLSSingleListener(NewGomegaWithT(t), tempDir, orderer, fabricRootDir, configtxgen)
testEtcdRaftOSNNoTLSSingleListener(NewGomegaWithT(t), tempDir, orderer, fabricRootDir, configtxgen, cryptoPath)
})
})

t.Run("Good", func(t *testing.T) {
// tests in this suite actually launch process with success, hence we need to avoid
// conflicts in listening port, opening files.
t.Run("TLS disabled dual listener", func(t *testing.T) {
gt = NewGomegaWithT(t)
tempDir, err := ioutil.TempDir("", "etcdraft-orderer-launch")
gt.Expect(err).NotTo(HaveOccurred())
defer os.RemoveAll(tempDir)

testEtcdRaftOSNNoTLSDualListener(gt, tempDir, orderer, fabricRootDir, configtxgen)
testEtcdRaftOSNNoTLSDualListener(gt, tempDir, orderer, fabricRootDir, configtxgen, cryptoPath)
})

t.Run("TLS enabled single listener", func(t *testing.T) {
gt = NewGomegaWithT(t)
tempDir, err := ioutil.TempDir("", "etcdraft-orderer-launch")
gt.Expect(err).NotTo(HaveOccurred())
defer os.RemoveAll(tempDir)

testEtcdRaftOSNSuccess(gt, tempDir, configtxgen, orderer, fabricRootDir)
testEtcdRaftOSNSuccess(gt, tempDir, configtxgen, orderer, fabricRootDir, cryptoPath)
})
})
}

func createBootstrapBlock(gt *GomegaWithT, tempDir, configtxgen, channel, profile string) string {
func copyYamlFiles(gt *GomegaWithT, src, dst string) {
for _, file := range []string{"configtx.yaml", "examplecom-config.yaml", "orderer.yaml"} {
fileBytes, err := ioutil.ReadFile(filepath.Join(src, file))
gt.Expect(err).NotTo(HaveOccurred())
err = ioutil.WriteFile(filepath.Join(dst, file), fileBytes, 0644)
gt.Expect(err).NotTo(HaveOccurred())
}
}

func generateBootstrapBlock(gt *GomegaWithT, tempDir, configtxgen, channel, profile string) string {
// create a genesis block for the specified channel and profile
genesisBlockPath := filepath.Join(tempDir, "genesis.block")
cmd := exec.Command(configtxgen, "-channelID", channel, "-profile", profile,
"-outputBlock", genesisBlockPath)
cmd.Env = append(cmd.Env, "FABRIC_CFG_PATH=testdata")
cmd := exec.Command(
configtxgen,
"-channelID", channel,
"-profile", profile,
"-outputBlock", genesisBlockPath,
"--configPath", tempDir,
)
configtxgenProcess, err := gexec.Start(cmd, nil, nil)
gt.Expect(err).NotTo(HaveOccurred())
gt.Eventually(configtxgenProcess, time.Minute).Should(gexec.Exit(0))
Expand All @@ -96,11 +104,27 @@ func createBootstrapBlock(gt *GomegaWithT, tempDir, configtxgen, channel, profil
return genesisBlockPath
}

func testEtcdRaftOSNSuccess(gt *GomegaWithT, tempDir, configtxgen, orderer, fabricRootDir string) {
genesisBlockPath := createBootstrapBlock(gt, tempDir, configtxgen, "system", "SampleEtcdRaftSystemChannel")
func generateCryptoMaterials(gt *GomegaWithT, cryptogen, path string) string {
cryptoPath := filepath.Join(path, "crypto")

cmd := exec.Command(
cryptogen,
"generate",
"--config", filepath.Join(path, "examplecom-config.yaml"),
"--output", cryptoPath,
)
cryptogenProcess, err := gexec.Start(cmd, nil, nil)
gt.Expect(err).NotTo(HaveOccurred())
gt.Eventually(cryptogenProcess, time.Minute).Should(gexec.Exit(0))

return cryptoPath
}

func testEtcdRaftOSNSuccess(gt *GomegaWithT, tempDir, configtxgen, orderer, fabricRootDir, cryptoPath string) {
genesisBlockPath := generateBootstrapBlock(gt, tempDir, configtxgen, "system", "SampleEtcdRaftSystemChannel")

// Launch the OSN
ordererProcess := launchOrderer(gt, orderer, tempDir, genesisBlockPath, fabricRootDir)
ordererProcess := launchOrderer(gt, orderer, tempDir, genesisBlockPath, fabricRootDir, cryptoPath)
defer ordererProcess.Kill()
// The following configuration parameters are not specified in the orderer.yaml, so let's ensure
// they are really configured autonomously via the localconfig code.
Expand All @@ -122,9 +146,9 @@ func testEtcdRaftOSNSuccess(gt *GomegaWithT, tempDir, configtxgen, orderer, fabr
gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("becomeLeader"))
}

func testEtcdRaftOSNFailureInvalidBootstrapBlock(gt *GomegaWithT, tempDir, orderer, fabricRootDir, configtxgen string) {
func testEtcdRaftOSNFailureInvalidBootstrapBlock(gt *GomegaWithT, tempDir, orderer, fabricRootDir, configtxgen, cryptoPath string) {
// create an application channel genesis block
genesisBlockPath := createBootstrapBlock(gt, tempDir, configtxgen, "mychannel", "SampleOrgChannel")
genesisBlockPath := generateBootstrapBlock(gt, tempDir, configtxgen, "mychannel", "SampleOrgChannel")
genesisBlockBytes, err := ioutil.ReadFile(genesisBlockPath)
gt.Expect(err).NotTo(HaveOccurred())

Expand All @@ -134,15 +158,15 @@ func testEtcdRaftOSNFailureInvalidBootstrapBlock(gt *GomegaWithT, tempDir, order
gt.Expect(err).NotTo(HaveOccurred())

// Launch the OSN
ordererProcess := launchOrderer(gt, orderer, tempDir, genesisBlockPath, fabricRootDir)
ordererProcess := launchOrderer(gt, orderer, tempDir, genesisBlockPath, fabricRootDir, cryptoPath)
defer ordererProcess.Kill()

expectedErr := "Failed validating bootstrap block: the block isn't a system channel block because it lacks ConsortiumsConfig"
gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say(expectedErr))
}

func testEtcdRaftOSNNoTLSSingleListener(gt *GomegaWithT, tempDir, orderer, fabricRootDir string, configtxgen string) {
genesisBlockPath := createBootstrapBlock(gt, tempDir, configtxgen, "system", "SampleEtcdRaftSystemChannel")
func testEtcdRaftOSNNoTLSSingleListener(gt *GomegaWithT, tempDir, orderer, fabricRootDir string, configtxgen, cryptoPath string) {
genesisBlockPath := generateBootstrapBlock(gt, tempDir, configtxgen, "system", "SampleEtcdRaftSystemChannel")

cmd := exec.Command(orderer)
cmd.Env = []string{
Expand All @@ -151,7 +175,7 @@ func testEtcdRaftOSNNoTLSSingleListener(gt *GomegaWithT, tempDir, orderer, fabri
"ORDERER_GENERAL_SYSTEMCHANNEL=system",
fmt.Sprintf("ORDERER_FILELEDGER_LOCATION=%s", filepath.Join(tempDir, "ledger")),
fmt.Sprintf("ORDERER_GENERAL_BOOTSTRAPFILE=%s", genesisBlockPath),
fmt.Sprintf("FABRIC_CFG_PATH=%s", filepath.Join(fabricRootDir, "sampleconfig")),
fmt.Sprintf("FABRIC_CFG_PATH=%s", tempDir),
}
ordererProcess, err := gexec.Start(cmd, nil, nil)
gt.Expect(err).NotTo(HaveOccurred())
Expand All @@ -161,11 +185,9 @@ func testEtcdRaftOSNNoTLSSingleListener(gt *GomegaWithT, tempDir, orderer, fabri
gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say(expectedErr))
}

func testEtcdRaftOSNNoTLSDualListener(gt *GomegaWithT, tempDir, orderer, fabricRootDir string, configtxgen string) {
cwd, err := os.Getwd()
gt.Expect(err).NotTo(HaveOccurred())

genesisBlockPath := createBootstrapBlock(gt, tempDir, configtxgen, "system", "SampleEtcdRaftSystemChannel")
func testEtcdRaftOSNNoTLSDualListener(gt *GomegaWithT, tempDir, orderer, fabricRootDir string, configtxgen, cryptoPath string) {
ordererTLSPath := filepath.Join(cryptoPath, "ordererOrganizations", "example.com", "orderers", "127.0.0.1.example.com", "tls")
genesisBlockPath := generateBootstrapBlock(gt, tempDir, configtxgen, "system", "SampleEtcdRaftSystemChannel")

cmd := exec.Command(orderer)
cmd.Env = []string{
Expand All @@ -178,14 +200,14 @@ func testEtcdRaftOSNNoTLSDualListener(gt *GomegaWithT, tempDir, orderer, fabricR
fmt.Sprintf("ORDERER_GENERAL_BOOTSTRAPFILE=%s", genesisBlockPath),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_LISTENPORT=%d", nextPort()),
"ORDERER_GENERAL_CLUSTER_LISTENADDRESS=127.0.0.1",
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERCERTIFICATE=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.crt")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERPRIVATEKEY=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.key")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.crt")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.key")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_ROOTCAS=[%s]", filepath.Join(cwd, "testdata", "example.com", "tls", "ca.crt")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERCERTIFICATE=%s", filepath.Join(ordererTLSPath, "server.crt")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERPRIVATEKEY=%s", filepath.Join(ordererTLSPath, "server.key")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=%s", filepath.Join(ordererTLSPath, "server.crt")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=%s", filepath.Join(ordererTLSPath, "server.key")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_ROOTCAS=[%s]", filepath.Join(ordererTLSPath, "ca.crt")),
fmt.Sprintf("ORDERER_CONSENSUS_WALDIR=%s", filepath.Join(tempDir, "wal")),
fmt.Sprintf("ORDERER_CONSENSUS_SNAPDIR=%s", filepath.Join(tempDir, "snapshot")),
fmt.Sprintf("FABRIC_CFG_PATH=%s", filepath.Join(fabricRootDir, "sampleconfig")),
fmt.Sprintf("FABRIC_CFG_PATH=%s", tempDir),
"ORDERER_OPERATIONS_LISTENADDRESS=127.0.0.1:0",
}
ordererProcess, err := gexec.Start(cmd, nil, nil)
Expand All @@ -196,10 +218,8 @@ func testEtcdRaftOSNNoTLSDualListener(gt *GomegaWithT, tempDir, orderer, fabricR
gt.Eventually(ordererProcess.Err, time.Minute).Should(gbytes.Say("becomeLeader"))
}

func launchOrderer(gt *GomegaWithT, orderer, tempDir, genesisBlockPath, fabricRootDir string) *gexec.Session {
cwd, err := os.Getwd()
gt.Expect(err).NotTo(HaveOccurred())

func launchOrderer(gt *GomegaWithT, orderer, tempDir, genesisBlockPath, fabricRootDir, cryptoPath string) *gexec.Session {
ordererTLSPath := filepath.Join(cryptoPath, "ordererOrganizations", "example.com", "orderers", "127.0.0.1.example.com", "tls")
// Launch the orderer process
cmd := exec.Command(orderer)
cmd.Env = []string{
Expand All @@ -213,17 +233,17 @@ func launchOrderer(gt *GomegaWithT, orderer, tempDir, genesisBlockPath, fabricRo
fmt.Sprintf("ORDERER_GENERAL_BOOTSTRAPFILE=%s", genesisBlockPath),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_LISTENPORT=%d", nextPort()),
"ORDERER_GENERAL_CLUSTER_LISTENADDRESS=127.0.0.1",
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERCERTIFICATE=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.crt")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERPRIVATEKEY=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.key")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.crt")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.key")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_ROOTCAS=[%s]", filepath.Join(cwd, "testdata", "example.com", "tls", "ca.crt")),
fmt.Sprintf("ORDERER_GENERAL_TLS_ROOTCAS=[%s]", filepath.Join(cwd, "testdata", "example.com", "tls", "ca.crt")),
fmt.Sprintf("ORDERER_GENERAL_TLS_CERTIFICATE=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.crt")),
fmt.Sprintf("ORDERER_GENERAL_TLS_PRIVATEKEY=%s", filepath.Join(cwd, "testdata", "example.com", "tls", "server.key")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERCERTIFICATE=%s", filepath.Join(ordererTLSPath, "server.crt")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_SERVERPRIVATEKEY=%s", filepath.Join(ordererTLSPath, "server.key")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=%s", filepath.Join(ordererTLSPath, "server.crt")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=%s", filepath.Join(ordererTLSPath, "server.key")),
fmt.Sprintf("ORDERER_GENERAL_CLUSTER_ROOTCAS=[%s]", filepath.Join(ordererTLSPath, "ca.crt")),
fmt.Sprintf("ORDERER_GENERAL_TLS_ROOTCAS=[%s]", filepath.Join(ordererTLSPath, "ca.crt")),
fmt.Sprintf("ORDERER_GENERAL_TLS_CERTIFICATE=%s", filepath.Join(ordererTLSPath, "server.crt")),
fmt.Sprintf("ORDERER_GENERAL_TLS_PRIVATEKEY=%s", filepath.Join(ordererTLSPath, "server.key")),
fmt.Sprintf("ORDERER_CONSENSUS_WALDIR=%s", filepath.Join(tempDir, "wal")),
fmt.Sprintf("ORDERER_CONSENSUS_SNAPDIR=%s", filepath.Join(tempDir, "snapshot")),
fmt.Sprintf("FABRIC_CFG_PATH=%s", filepath.Join(fabricRootDir, "sampleconfig")),
fmt.Sprintf("FABRIC_CFG_PATH=%s", tempDir),
}
sess, err := gexec.Start(cmd, nil, nil)
gt.Expect(err).NotTo(HaveOccurred())
Expand Down
29 changes: 27 additions & 2 deletions orderer/common/server/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net"
"net/http"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
Expand Down Expand Up @@ -41,6 +42,8 @@ import (
server_mocks "github.com/hyperledger/fabric/orderer/common/server/mocks"
"github.com/hyperledger/fabric/orderer/consensus"
"github.com/hyperledger/fabric/protoutil"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
Expand Down Expand Up @@ -455,13 +458,35 @@ func TestInitializeGrpcServer(t *testing.T) {
})
}

// generateCryptoMaterials uses cryptogen to generate the necessary
// MSP files and TLS certificates
func generateCryptoMaterials(t *testing.T, cryptogen string) string {
gt := NewGomegaWithT(t)
cryptoPath := filepath.Join(tempDir, "crypto")

cmd := exec.Command(
cryptogen,
"generate",
"--config", filepath.Join(tempDir, "examplecom-config.yaml"),
"--output", cryptoPath,
)
cryptogenProcess, err := gexec.Start(cmd, nil, nil)
gt.Expect(err).NotTo(HaveOccurred())
gt.Eventually(cryptogenProcess, time.Minute).Should(gexec.Exit(0))

return cryptoPath
}

func TestUpdateTrustedRoots(t *testing.T) {
cleanup := configtest.SetDevFabricConfigPath(t)
defer cleanup()

genesisFile := produceGenesisFile(t, genesisconfig.SampleDevModeSoloProfile, "testchannelid")
defer os.Remove(genesisFile)

cryptoPath := generateCryptoMaterials(t, cryptogen)
defer os.RemoveAll(cryptoPath)

// get a free random port
listenAddr := func() string {
l, _ := net.Listen("tcp", "localhost:0")
Expand Down Expand Up @@ -529,8 +554,8 @@ func TestUpdateTrustedRoots(t *testing.T) {
TLS: localconfig.TLS{
Enabled: true,
ClientAuthRequired: true,
PrivateKey: filepath.Join(".", "testdata", "example.com", "tls", "server.key"),
Certificate: filepath.Join(".", "testdata", "example.com", "tls", "server.crt"),
PrivateKey: filepath.Join(cryptoPath, "ordererOrganizations", "example.com", "orderers", "127.0.0.1.example.com", "tls", "server.key"),
Certificate: filepath.Join(cryptoPath, "ordererOrganizations", "example.com", "orderers", "127.0.0.1.example.com", "tls", "server.crt"),
},
},
}
Expand Down
Loading

0 comments on commit f5799c0

Please sign in to comment.