Skip to content
Open
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
22 changes: 22 additions & 0 deletions common/tools/armageddon/armageddon.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,28 @@ func generateConfigAndCrypto(genConfigFile **os.File, outputDir *string, sampleC
os.Exit(-1)
}
}

// generate user config yaml file for each peer
for _, peer := range networkConfig.Peers {
userTLSPrivateKeyPath := filepath.Join(*outputDir, "crypto", "peerOrganizations", peer, "tls", "key.pem")
userTLSCertPath := filepath.Join(*outputDir, "crypto", "peerOrganizations", peer, "tls", "tls-cert.pem")
mspDir := filepath.Join(*outputDir, "crypto", "peerOrganizations", peer, "msp")

userConfig, err := NewUserConfig(mspDir, userTLSPrivateKeyPath, userTLSCertPath, tlsCACertsBytesPartiesCollection, networkConfig)
if err != nil {
fmt.Fprintf(os.Stderr, "Error creating user config: %s", err)
os.Exit(-1)
}

peerConfigDir := path.Join(*outputDir, "config", peer)
os.MkdirAll(peerConfigDir, 0o755)

err = utils.WriteToYAML(userConfig, filepath.Join(peerConfigDir, "user_config.yaml"))
if err != nil {
fmt.Fprintf(os.Stderr, "Error generating user config yaml: %s", err)
os.Exit(-1)
}
}
}

func getConfigFileContent(genConfigFile **os.File) (*genconfig.Network, error) {
Expand Down
8 changes: 8 additions & 0 deletions common/tools/armageddon/armageddon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,14 @@ func checkConfigDir(outputDir string) error {

partyDir := filepath.Join(configPath, party.Name())

if strings.HasPrefix(party.Name(), "peer") {
filePath := filepath.Join(partyDir, "user_config.yaml")
if !fileExists(filePath) {
return fmt.Errorf("missing file: %s\n", filePath)
}
continue
}

for _, file := range requiredPartyFiles {
filePath := filepath.Join(partyDir, file)
if !fileExists(filePath) {
Expand Down
161 changes: 158 additions & 3 deletions common/tools/armageddon/cryptogen.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,34 @@ func createNetworkCryptoMaterial(dir string, network *genconfig.Network) error {
// collect all node IPs as they are includes as SANs when generating TLS certificates.
nodesIPs := getNodeIPs(network)

peersTLSCAs, peersSignCAs, err := createCAsPerPeer(dir, network)
if err != nil {
return err
}

// create crypto material for each peer and write the crypto into files
for _, peer := range network.Peers {
// choose a TLS CA and a signing CA of the peer
signCA := peersSignCAs[peer]
tlsCA := peersTLSCAs[peer]

// signing crypto to admin of the organization
err = createAdminSignCertAndPrivateKeyForPeer(signCA, dir, peer)
if err != nil {
return err
}
// create TLS and signing crypto for the peer
err = createTLSCertKeyPairForPeer(tlsCA, dir, peer, nodesIPs)
if err != nil {
return err
}
// create signing crypto for the peer
err = createSignCertAndPrivateKeyForPeer(signCA, dir, peer, nodesIPs)
if err != nil {
return err
}
}

// create crypto material for each party's nodes and write the crypto into files
for _, party := range network.Parties {
// choose a TLS CA and a signing CA of the party
Expand Down Expand Up @@ -268,6 +296,42 @@ func createCAsPerParty(dir string, network *genconfig.Network) (map[types.PartyI
return partiesTLSCAs, partiesSignCAs, nil
}

// createCAsPerPeer creates a TLS CA and a signing CA for each peer and write the ca's certificates into files.
func createCAsPerPeer(dir string, network *genconfig.Network) (map[string]*ca.CA, map[string]*ca.CA, error) {
peersTLSCAs := make(map[string]*ca.CA)
peersSignCAs := make(map[string]*ca.CA)

for _, peer := range network.Peers {
// create a TLS CA for the peer
pathToTLSCACert := filepath.Join(dir, "crypto", "peerOrganizations", peer, "tlsca")
tlsCA, err := ca.NewCA(pathToTLSCACert, "tlsCA", "tlsca", "US", "California", "San Francisco", "ARMA", "addr", "12345", "ecdsa")
if err != nil {
return nil, nil, fmt.Errorf("err: %s, failed creating a TLS CA for peer %s", err, peer)
}
err = copyPEMFiles(pathToTLSCACert, filepath.Join(dir, "crypto", "peerOrganizations", peer, "msp", "tlscacerts"))
if err != nil {
return nil, nil, err
}

peersTLSCAs[peer] = tlsCA

// create a Signing CA for the peer
pathToSignCACert := filepath.Join(dir, "crypto", "peerOrganizations", peer, "ca")
signCA, err := ca.NewCA(pathToSignCACert, "signCA", "ca", "US", "California", "San Francisco", "ARMA", "addr", "12345", "ecdsa")
if err != nil {
return nil, nil, fmt.Errorf("err: %s, failed creating a signing CA for peer %s", err, peer)
}
err = copyPEMFiles(pathToSignCACert, filepath.Join(dir, "crypto", "peerOrganizations", peer, "msp", "cacerts"))
if err != nil {
return nil, nil, err
}

peersSignCAs[peer] = signCA
}

return peersTLSCAs, peersSignCAs, nil
}

// createTLSCertKeyPairForNode creates a TLS cert,key pair signed by a corresponding CA for an Arma node and write them into files.
func createTLSCertKeyPairForNode(ca *ca.CA, dir string, endpoint string, role string, partyID types.PartyID, nodesIPs []string) error {
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
Expand All @@ -290,6 +354,31 @@ func createTLSCertKeyPairForNode(ca *ca.CA, dir string, endpoint string, role st
return nil
}

// createTLSCertKeyPairForPeer creates a TLS cert,key pair signed by a corresponding CA for a peer and write them into files.
func createTLSCertKeyPairForPeer(ca *ca.CA, dir string, peer string, nodesIPs []string) error {
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return fmt.Errorf("err: %s, failed creating private key for %s", err, peer)
}
privateKeyBytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
if err != nil {
return fmt.Errorf("err: %s, failed marshaling private key for %s", err, peer)
}

_, err = ca.SignCertificate(filepath.Join(dir, "crypto", "peerOrganizations", peer, "tls"), "tls", nil, nodesIPs, GetPublicKey(privateKey), x509.KeyUsageCertSign|x509.KeyUsageCRLSign, []x509.ExtKeyUsage{
x509.ExtKeyUsageClientAuth,
x509.ExtKeyUsageServerAuth,
})
if err != nil {
return err
}
err = utils.WritePEMToFile(filepath.Join(dir, "crypto", "peerOrganizations", peer, "tls", "key.pem"), "PRIVATE KEY", privateKeyBytes)
if err != nil {
return err
}
return nil
}

// createUserTLSCertKeyPair creates a TLS cert,key pair signed by a corresponding CA for a user.
func createUserTLSCertKeyPair(ca *ca.CA, dir string, partyID types.PartyID, nodesIPs []string) error {
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
Expand Down Expand Up @@ -332,6 +421,28 @@ func createSignCertAndPrivateKeyForNode(ca *ca.CA, dir string, endpoint string,
return nil
}

// createSignCertAndPrivateKeyForPeer creates a signed certificate with a corresponding private key used for signing and write them into files.
func createSignCertAndPrivateKeyForPeer(ca *ca.CA, dir string, peer string, nodesIPs []string) error {
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return fmt.Errorf("err: %s, failed creating private key for %s", err, peer)
}
privateKeyBytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
if err != nil {
return fmt.Errorf("err: %s, failed marshaling private key for %s", err, peer)
}

_, err = ca.SignCertificate(filepath.Join(dir, "crypto", "peerOrganizations", peer, "signcerts"), "sign", nil, nodesIPs, GetPublicKey(privateKey), x509.KeyUsageDigitalSignature, []x509.ExtKeyUsage{})
if err != nil {
return err
}
err = utils.WritePEMToFile(filepath.Join(dir, "crypto", "peerOrganizations", peer, "keystore", "priv_sk"), "PRIVATE KEY", privateKeyBytes)
if err != nil {
return err
}
return nil
}

// createUserSignCertAndPrivateKey creates for user a signed certificate with a corresponding private key used for signing and write them into files.
func createUserSignCertAndPrivateKey(ca *ca.CA, dir string, partyID types.PartyID, nodesIPs []string) error {
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
Expand Down Expand Up @@ -376,16 +487,45 @@ func createAdminSignCertAndPrivateKey(ca *ca.CA, dir string, partyID types.Party
return nil
}

// createAdminSignCertAndPrivateKeyForPeer creates for admin of a peer a signed certificate with a corresponding private key.
func createAdminSignCertAndPrivateKeyForPeer(ca *ca.CA, dir string, peer string) error {
privateKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil {
return fmt.Errorf("err: %s, failed creating private key for admin of org %s", err, peer)
}
privateKeyBytes, err := x509.MarshalPKCS8PrivateKey(privateKey)
if err != nil {
return fmt.Errorf("err: %s, failed marshaling private key for admin of org %s", err, peer)
}

_, err = ca.SignCertificate(filepath.Join(dir, "crypto", "peerOrganizations", peer, "msp", "admincerts"), fmt.Sprintf("Admin@%s", peer), []string{msp.ADMINOU}, nil, GetPublicKey(privateKey), x509.KeyUsageDigitalSignature, []x509.ExtKeyUsage{})
if err != nil {
return err
}
err = utils.WritePEMToFile(filepath.Join(dir, "crypto", "peerOrganizations", peer, "msp", "admincerts", "keystore", "priv_sk"), "PRIVATE KEY", privateKeyBytes)
if err != nil {
return err
}
return nil
}

// generateNetworkCryptoConfigFolderStructure creates folders where the crypto material is written to.
func generateNetworkCryptoConfigFolderStructure(dir string, network *genconfig.Network) error {
var folders []string

rootDir := filepath.Join(dir, "crypto", "ordererOrganizations")
folders = append(folders, rootDir)
ordererRootDir := filepath.Join(dir, "crypto", "ordererOrganizations")
folders = append(folders, ordererRootDir)
peerRootDir := filepath.Join(dir, "crypto", "peerOrganizations")
folders = append(folders, peerRootDir)

for _, p := range network.Parties {
folders = generateOrdererOrg(rootDir, folders, int(p.ID), len(p.BatchersEndpoints))
folders = generateOrdererOrg(ordererRootDir, folders, int(p.ID), len(p.BatchersEndpoints))
}

for _, peer := range network.Peers {
folders = generatePeerOrg(peerRootDir, folders, peer)
}

for _, folder := range folders {
err := os.MkdirAll(folder, 0o755)
if err != nil {
Expand All @@ -395,6 +535,21 @@ func generateNetworkCryptoConfigFolderStructure(dir string, network *genconfig.N
return nil
}

// generatePeerOrg generates folders for a peer organization.
func generatePeerOrg(rootDir string, folders []string, peerID string) []string {
orgDir := filepath.Join(rootDir, peerID)
folders = append(folders, orgDir)
folders = append(folders, filepath.Join(orgDir, "tls"))
folders = append(folders, filepath.Join(orgDir, signcerts))
folders = append(folders, filepath.Join(orgDir, keystore))
folders = append(folders, filepath.Join(orgDir, "msp", cacerts))
folders = append(folders, filepath.Join(orgDir, "msp", tlscacerts))
folders = append(folders, filepath.Join(orgDir, "msp", admincerts))
folders = append(folders, filepath.Join(orgDir, "msp", admincerts, keystore))

return folders
}

// generateOrdererOrg generates folders for an orderer organization.
// In general, an organization can include one or more parties, but this crypto-gen tool is designed for the scenario where each organization corresponds to a single party.
// A local MSP directory is also created for each party's node (i.e., Router, Batcher, Consenter and Assembler) which defines the identity of that node.
Expand Down
2 changes: 1 addition & 1 deletion config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func TestExtractAppTrustedRootsFromConfigBlock(t *testing.T) {
require.NoError(t, err)

res := config.ExtractAppTrustedRootsFromConfigBlock(bundle)
require.Equal(t, len(res), 4)
require.Equal(t, len(res), 1)
})
}

Expand Down
31 changes: 25 additions & 6 deletions config/generate/config_block_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package generate

import (
"fmt"
"os"
"path/filepath"
"strings"

Expand Down Expand Up @@ -68,13 +69,17 @@ func CreateProfile(dir string, sharedConfigYaml *config.SharedConfigYaml, shared
profile.Orderer.Arma.Path = sharedConfigPath

templateAppOrg := profile.Application.Organizations[0]
profile.Application.Organizations = make([]*configtxgen.Organization, len(sharedConfigYaml.PartiesConfig))
peers, err := buildPeerNames(filepath.Join(dir, "crypto", "peerOrganizations"))
if err != nil {
return nil, err
}
profile.Application.Organizations = make([]*configtxgen.Organization, len(peers))

for i := range sharedConfigYaml.PartiesConfig {
for i, peer := range peers {
org := &configtxgen.Organization{
Name: fmt.Sprintf("org%d", i+1),
ID: fmt.Sprintf("org%d", i+1),
MSPDir: filepath.Join(dir, "crypto", "ordererOrganizations", fmt.Sprintf("org%d", i+1), "msp"),
Name: peer,
ID: peer,
MSPDir: filepath.Join(dir, "crypto", "peerOrganizations", peer, "msp"),
MSPType: templateAppOrg.MSPType,
Policies: make(map[string]*configtxgen.Policy),
AnchorPeers: templateAppOrg.AnchorPeers,
Expand All @@ -86,7 +91,7 @@ func CreateProfile(dir string, sharedConfigYaml *config.SharedConfigYaml, shared
for key, policy := range templateAppOrg.Policies {
orgPolicy := &configtxgen.Policy{
Type: policy.Type,
Rule: strings.ReplaceAll(policy.Rule, "SampleOrg", fmt.Sprintf("org%d", i+1)),
Rule: strings.ReplaceAll(policy.Rule, "SampleOrg", peer),
}
org.Policies[key] = orgPolicy
}
Expand Down Expand Up @@ -126,6 +131,20 @@ func CreateProfile(dir string, sharedConfigYaml *config.SharedConfigYaml, shared
return profile, nil
}

func buildPeerNames(path string) ([]string, error) {
entries, err := os.ReadDir(path)
if err != nil {
return nil, err
}
var peers []string
for _, e := range entries {
if e.IsDir() {
peers = append(peers, filepath.Base(filepath.Join(path, e.Name())))
}
}
return peers, nil
}

func buildOrdererEndpoints(id uint32, routerHost string, routerPort int, assemblerHost string, assemblerPort int) []*types.OrdererEndpoint {
return []*types.OrdererEndpoint{
{Host: routerHost, Port: routerPort, ID: id, API: []string{types.Broadcast}},
Expand Down
1 change: 1 addition & 0 deletions config/generate/network_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type Network struct {
UseTLSRouter string `yaml:"UseTLSRouter"`
UseTLSAssembler string `yaml:"UseTLSAssembler"`
MaxPartyID types.PartyID `yaml:"MaxPartyID"`
Peers []string `yaml:"Peers"`
}

type Party struct {
Expand Down
2 changes: 1 addition & 1 deletion node/consensus/consensus_real_reconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ func TestConsensusWithRealConfigUpdate(t *testing.T) {
require.NoError(t, err)
configUpdateBuilder := configutil.NewConfigUpdateBuilder(t, dir, filepath.Join(oneMoreConfigBlockStoreDir, "config.block"))
configUpdatePbData := configUpdateBuilder.UpdateOrderingEndpoint(t, consenterPartyToUpdate, nodeIP, newPort)
env := configutil.CreateConfigTX(t, dir, parties[0:4], 1, configUpdatePbData)
env := configutil.CreateConfigTX(t, dir, parties[0:4], int(parties[0]), configUpdatePbData)
configReq := &protos.Request{
Payload: env.Payload,
Signature: env.Signature,
Expand Down
Loading
Loading