Read first client cert from cert directory

Allow client applications to work regardless of whether network was creating using a CA or cryptogen since they create different client certificate file names.

Signed-off-by: Mark S. Lewis <Mark.S.Lewis@outlook.com>
This commit is contained in:
Mark S. Lewis 2024-02-29 18:01:22 +00:00 committed by Dave Enyeart
parent db86460086
commit a5eea8cd5c
11 changed files with 148 additions and 98 deletions

View file

@ -28,8 +28,8 @@ import (
const (
mspID = "Org1MSP"
cryptoPath = "../../test-network/organizations/peerOrganizations/org1.example.com"
certPath = cryptoPath + "/users/User1@org1.example.com/msp/signcerts/cert.pem"
keyPath = cryptoPath + "/users/User1@org1.example.com/msp/keystore/"
certPath = cryptoPath + "/users/User1@org1.example.com/msp/signcerts"
keyPath = cryptoPath + "/users/User1@org1.example.com/msp/keystore"
tlsCertPath = cryptoPath + "/peers/peer0.org1.example.com/tls/ca.crt"
peerEndpoint = "localhost:7051"
gatewayPeer = "peer0.org1.example.com"
@ -86,7 +86,12 @@ func main() {
// newGrpcConnection creates a gRPC connection to the Gateway server.
func newGrpcConnection() *grpc.ClientConn {
certificate, err := loadCertificate(tlsCertPath)
certificatePEM, err := os.ReadFile(tlsCertPath)
if err != nil {
panic(fmt.Errorf("failed to read TLS certifcate file: %w", err))
}
certificate, err := identity.CertificateFromPEM(certificatePEM)
if err != nil {
panic(err)
}
@ -105,7 +110,12 @@ func newGrpcConnection() *grpc.ClientConn {
// newIdentity creates a client identity for this Gateway connection using an X.509 certificate.
func newIdentity() *identity.X509Identity {
certificate, err := loadCertificate(certPath)
certificatePEM, err := readFirstFile(certPath)
if err != nil {
panic(fmt.Errorf("failed to read certificate file: %w", err))
}
certificate, err := identity.CertificateFromPEM(certificatePEM)
if err != nil {
panic(err)
}
@ -118,22 +128,9 @@ func newIdentity() *identity.X509Identity {
return id
}
func loadCertificate(filename string) (*x509.Certificate, error) {
certificatePEM, err := os.ReadFile(filename)
if err != nil {
return nil, fmt.Errorf("failed to read certificate file: %w", err)
}
return identity.CertificateFromPEM(certificatePEM)
}
// newSign creates a function that generates a digital signature from a message digest using a private key.
func newSign() identity.Sign {
files, err := os.ReadDir(keyPath)
if err != nil {
panic(fmt.Errorf("failed to read private key directory: %w", err))
}
privateKeyPEM, err := os.ReadFile(path.Join(keyPath, files[0].Name()))
privateKeyPEM, err := readFirstFile(keyPath)
if err != nil {
panic(fmt.Errorf("failed to read private key file: %w", err))
}
@ -151,6 +148,20 @@ func newSign() identity.Sign {
return sign
}
func readFirstFile(dirPath string) ([]byte, error) {
dir, err := os.Open(dirPath)
if err != nil {
return nil, err
}
fileNames, err := dir.Readdirnames(1)
if err != nil {
return nil, err
}
return os.ReadFile(path.Join(dirPath, fileNames[0]))
}
// This type of transaction would typically only be run once by an application the first time it was started after its
// initial deployment. A new version of the chaincode deployed later would likely not need to run an "init" function.
func initLedger(contract *client.Contract) {
@ -235,20 +246,24 @@ func exampleErrorHandling(contract *client.Contract) {
fmt.Println("*** Successfully caught the error:")
switch err := err.(type) {
case *client.EndorseError:
fmt.Printf("Endorse error for transaction %s with gRPC status %v: %s\n", err.TransactionID, status.Code(err), err)
case *client.SubmitError:
fmt.Printf("Submit error for transaction %s with gRPC status %v: %s\n", err.TransactionID, status.Code(err), err)
case *client.CommitStatusError:
var endorseErr *client.EndorseError
var submitErr *client.SubmitError
var commitStatusErr *client.CommitStatusError
var commitErr *client.CommitError
if errors.As(err, &endorseErr) {
fmt.Printf("Endorse error for transaction %s with gRPC status %v: %s\n", endorseErr.TransactionID, status.Code(endorseErr), endorseErr)
} else if errors.As(err, &submitErr) {
fmt.Printf("Submit error for transaction %s with gRPC status %v: %s\n", submitErr.TransactionID, status.Code(submitErr), submitErr)
} else if errors.As(err, &commitStatusErr) {
if errors.Is(err, context.DeadlineExceeded) {
fmt.Printf("Timeout waiting for transaction %s commit status: %s", err.TransactionID, err)
fmt.Printf("Timeout waiting for transaction %s commit status: %s", commitStatusErr.TransactionID, commitStatusErr)
} else {
fmt.Printf("Error obtaining commit status for transaction %s with gRPC status %v: %s\n", err.TransactionID, status.Code(err), err)
fmt.Printf("Error obtaining commit status for transaction %s with gRPC status %v: %s\n", commitStatusErr.TransactionID, status.Code(commitStatusErr), commitStatusErr)
}
case *client.CommitError:
fmt.Printf("Transaction %s failed to commit with status %d: %s\n", err.TransactionID, int32(err.Code), err)
default:
} else if errors.As(err, &commitErr) {
fmt.Printf("Transaction %s failed to commit with status %d: %s\n", commitErr.TransactionID, int32(commitErr.Code), err)
} else {
panic(fmt.Errorf("unexpected error type %T: %w", err, err))
}

View file

@ -41,7 +41,7 @@ public final class App {
// Path to crypto materials.
private static final Path CRYPTO_PATH = Paths.get("../../test-network/organizations/peerOrganizations/org1.example.com");
// Path to user certificate.
private static final Path CERT_PATH = CRYPTO_PATH.resolve(Paths.get("users/User1@org1.example.com/msp/signcerts/cert.pem"));
private static final Path CERT_DIR_PATH = CRYPTO_PATH.resolve(Paths.get("users/User1@org1.example.com/msp/signcerts"));
// Path to user private key directory.
private static final Path KEY_DIR_PATH = CRYPTO_PATH.resolve(Paths.get("users/User1@org1.example.com/msp/keystore"));
// Path to peer tls certificate.
@ -84,21 +84,21 @@ public final class App {
}
private static Identity newIdentity() throws IOException, CertificateException {
var certReader = Files.newBufferedReader(CERT_PATH);
var certificate = Identities.readX509Certificate(certReader);
return new X509Identity(MSP_ID, certificate);
try (var certReader = Files.newBufferedReader(getFirstFilePath(CERT_DIR_PATH))) {
var certificate = Identities.readX509Certificate(certReader);
return new X509Identity(MSP_ID, certificate);
}
}
private static Signer newSigner() throws IOException, InvalidKeyException {
var keyReader = Files.newBufferedReader(getPrivateKeyPath());
var privateKey = Identities.readPrivateKey(keyReader);
return Signers.newPrivateKeySigner(privateKey);
try (var keyReader = Files.newBufferedReader(getFirstFilePath(KEY_DIR_PATH))) {
var privateKey = Identities.readPrivateKey(keyReader);
return Signers.newPrivateKeySigner(privateKey);
}
}
private static Path getPrivateKeyPath() throws IOException {
try (var keyFiles = Files.list(KEY_DIR_PATH)) {
private static Path getFirstFilePath(Path dirPath) throws IOException {
try (var keyFiles = Files.list(dirPath)) {
return keyFiles.findFirst().orElseThrow();
}
}

View file

@ -21,8 +21,8 @@ const cryptoPath = envOrDefault('CRYPTO_PATH', path.resolve(__dirname, '..', '..
// Path to user private key directory.
const keyDirectoryPath = envOrDefault('KEY_DIRECTORY_PATH', path.resolve(cryptoPath, 'users', 'User1@org1.example.com', 'msp', 'keystore'));
// Path to user certificate.
const certPath = envOrDefault('CERT_PATH', path.resolve(cryptoPath, 'users', 'User1@org1.example.com', 'msp', 'signcerts', 'cert.pem'));
// Path to user certificate directory.
const certDirectoryPath = envOrDefault('CERT_DIRECTORY_PATH', path.resolve(cryptoPath, 'users', 'User1@org1.example.com', 'msp', 'signcerts'));
// Path to peer tls certificate.
const tlsCertPath = envOrDefault('TLS_CERT_PATH', path.resolve(cryptoPath, 'peers', 'peer0.org1.example.com', 'tls', 'ca.crt'));
@ -106,13 +106,18 @@ async function newGrpcConnection(): Promise<grpc.Client> {
}
async function newIdentity(): Promise<Identity> {
const certPath = await getFirstDirFileName(certDirectoryPath);
const credentials = await fs.readFile(certPath);
return { mspId, credentials };
}
async function getFirstDirFileName(dirPath: string): Promise<string> {
const files = await fs.readdir(dirPath);
return path.join(dirPath, files[0]);
}
async function newSigner(): Promise<Signer> {
const files = await fs.readdir(keyDirectoryPath);
const keyPath = path.resolve(keyDirectoryPath, files[0]);
const keyPath = await getFirstDirFileName(keyDirectoryPath);
const privateKeyPem = await fs.readFile(keyPath);
const privateKey = crypto.createPrivateKey(privateKeyPem);
return signers.newPrivateKeySigner(privateKey);
@ -231,7 +236,7 @@ async function displayInputParameters(): Promise<void> {
console.log(`mspId: ${mspId}`);
console.log(`cryptoPath: ${cryptoPath}`);
console.log(`keyDirectoryPath: ${keyDirectoryPath}`);
console.log(`certPath: ${certPath}`);
console.log(`certDirectoryPath: ${certDirectoryPath}`);
console.log(`tlsCertPath: ${tlsCertPath}`);
console.log(`peerEndpoint: ${peerEndpoint}`);
console.log(`peerHostAlias: ${peerHostAlias}`);

View file

@ -20,8 +20,8 @@ import (
const (
mspID = "Org1MSP"
cryptoPath = "../../test-network/organizations/peerOrganizations/org1.example.com"
certPath = cryptoPath + "/users/User1@org1.example.com/msp/signcerts/cert.pem"
keyPath = cryptoPath + "/users/User1@org1.example.com/msp/keystore/"
certPath = cryptoPath + "/users/User1@org1.example.com/msp/signcerts"
keyPath = cryptoPath + "/users/User1@org1.example.com/msp/keystore"
tlsCertPath = cryptoPath + "/peers/peer0.org1.example.com/tls/ca.crt"
peerEndpoint = "localhost:7051"
gatewayPeer = "peer0.org1.example.com"
@ -29,7 +29,12 @@ const (
// newGrpcConnection creates a gRPC connection to the Gateway server.
func newGrpcConnection() *grpc.ClientConn {
certificate, err := loadCertificate(tlsCertPath)
certificatePEM, err := os.ReadFile(tlsCertPath)
if err != nil {
panic(fmt.Errorf("failed to read TLS certifcate file: %w", err))
}
certificate, err := identity.CertificateFromPEM(certificatePEM)
if err != nil {
panic(err)
}
@ -48,7 +53,12 @@ func newGrpcConnection() *grpc.ClientConn {
// newIdentity creates a client identity for this Gateway connection using an X.509 certificate.
func newIdentity() *identity.X509Identity {
certificate, err := loadCertificate(certPath)
certificatePEM, err := readFirstFile(certPath)
if err != nil {
panic(fmt.Errorf("failed to read certificate file: %w", err))
}
certificate, err := identity.CertificateFromPEM(certificatePEM)
if err != nil {
panic(err)
}
@ -71,12 +81,7 @@ func loadCertificate(filename string) (*x509.Certificate, error) {
// newSign creates a function that generates a digital signature from a message digest using a private key.
func newSign() identity.Sign {
files, err := os.ReadDir(keyPath)
if err != nil {
panic(fmt.Errorf("failed to read private key directory: %w", err))
}
privateKeyPEM, err := os.ReadFile(path.Join(keyPath, files[0].Name()))
privateKeyPEM, err := readFirstFile(keyPath)
if err != nil {
panic(fmt.Errorf("failed to read private key file: %w", err))
}
@ -93,3 +98,17 @@ func newSign() identity.Sign {
return sign
}
func readFirstFile(dirPath string) ([]byte, error) {
dir, err := os.Open(dirPath)
if err != nil {
return nil, err
}
fileNames, err := dir.Readdirnames(1)
if err != nil {
return nil, err
}
return os.ReadFile(path.Join(dirPath, fileNames[0]))
}

View file

@ -24,7 +24,7 @@ public final class Connections {
// Path to crypto materials.
private static final Path cryptoPath = Paths.get("..", "..", "test-network", "organizations", "peerOrganizations", "org1.example.com");
// Path to user certificate.
private static final Path certPath = cryptoPath.resolve(Paths.get("users", "User1@org1.example.com", "msp", "signcerts", "cert.pem"));
private static final Path certDirPath = cryptoPath.resolve(Paths.get("users", "User1@org1.example.com", "msp", "signcerts"));
// Path to user private key directory.
private static final Path keyDirPath = cryptoPath.resolve(Paths.get("users", "User1@org1.example.com", "msp", "keystore"));
// Path to peer tls certificate.
@ -50,22 +50,21 @@ public final class Connections {
}
public static Identity newIdentity() throws IOException, CertificateException {
var certReader = Files.newBufferedReader(certPath);
var certificate = Identities.readX509Certificate(certReader);
return new X509Identity(mspID, certificate);
try (var certReader = Files.newBufferedReader(getFirstFilePath(certDirPath))) {
var certificate = Identities.readX509Certificate(certReader);
return new X509Identity(mspID, certificate);
}
}
public static Signer newSigner() throws IOException, InvalidKeyException {
var keyReader = Files.newBufferedReader(getPrivateKeyPath());
var privateKey = Identities.readPrivateKey(keyReader);
return Signers.newPrivateKeySigner(privateKey);
}
private static Path getPrivateKeyPath() throws IOException {
try (var keyFiles = Files.list(keyDirPath)) {
return keyFiles.findFirst().orElseThrow();
try (var keyReader = Files.newBufferedReader(getFirstFilePath(keyDirPath))) {
var privateKey = Identities.readPrivateKey(keyReader);
return Signers.newPrivateKeySigner(privateKey);
}
}
}
private static Path getFirstFilePath(Path dirPath) throws IOException {
try (var keyFiles = Files.list(dirPath)) {
return keyFiles.findFirst().orElseThrow();
}
}}

View file

@ -19,7 +19,7 @@ const cryptoPath = path.resolve(__dirname, '..', '..', '..', 'test-network', 'or
const keyDirectoryPath = path.resolve(cryptoPath, 'users', 'User1@org1.example.com', 'msp', 'keystore');
// Path to user certificate.
const certPath = path.resolve(cryptoPath, 'users', 'User1@org1.example.com', 'msp', 'signcerts', 'cert.pem');
const certDirectoryPath = path.resolve(cryptoPath, 'users', 'User1@org1.example.com', 'msp', 'signcerts');
// Path to peer tls certificate.
const tlsCertPath = path.resolve(cryptoPath, 'peers', 'peer0.org1.example.com', 'tls', 'ca.crt');
@ -36,14 +36,19 @@ export async function newGrpcConnection(): Promise<grpc.Client> {
}
export async function newIdentity(): Promise<Identity> {
const certPath = await getFirstDirFileName(certDirectoryPath);
const credentials = await fs.readFile(certPath);
return { mspId, credentials };
}
export async function newSigner(): Promise<Signer> {
const files = await fs.readdir(keyDirectoryPath);
const keyPath = path.resolve(keyDirectoryPath, files[0]);
const keyPath = await getFirstDirFileName(keyDirectoryPath);
const privateKeyPem = await fs.readFile(keyPath);
const privateKey = crypto.createPrivateKey(privateKeyPem);
return signers.newPrivateKeySigner(privateKey);
}
async function getFirstDirFileName(dirPath: string): Promise<string> {
const files = await fs.readdir(dirPath);
return path.join(dirPath, files[0]);
}

View file

@ -7,7 +7,7 @@
import { connect, Contract } from '@hyperledger/fabric-gateway';
import { TextDecoder } from 'util';
import {
certPathOrg1, certPathOrg2, keyDirectoryPathOrg1, keyDirectoryPathOrg2, newGrpcConnection, newIdentity,
certDirectoryPathOrg1, certDirectoryPathOrg2, keyDirectoryPathOrg1, keyDirectoryPathOrg2, newGrpcConnection, newIdentity,
newSigner, peerEndpointOrg1, peerEndpointOrg2, peerNameOrg1, peerNameOrg2, tlsCertPathOrg1, tlsCertPathOrg2
} from './connect';
@ -39,7 +39,7 @@ async function main(): Promise<void> {
const gatewayOrg1 = connect({
client: clientOrg1,
identity: await newIdentity(certPathOrg1, mspIdOrg1),
identity: await newIdentity(certDirectoryPathOrg1, mspIdOrg1),
signer: await newSigner(keyDirectoryPathOrg1),
});
@ -51,7 +51,7 @@ async function main(): Promise<void> {
const gatewayOrg2 = connect({
client: clientOrg2,
identity: await newIdentity(certPathOrg2, mspIdOrg2),
identity: await newIdentity(certDirectoryPathOrg2, mspIdOrg2),
signer: await newSigner(keyDirectoryPathOrg2),
});

View file

@ -32,13 +32,12 @@ export const keyDirectoryPathOrg1 = path.resolve(
);
// Path to org1 user certificate.
export const certPathOrg1 = path.resolve(
export const certDirectoryPathOrg1 = path.resolve(
cryptoPathOrg1,
'users',
'User1@org1.example.com',
'msp',
'signcerts',
'cert.pem'
'signcerts'
);
// Path to org1 peer tls certificate.
@ -72,13 +71,12 @@ export const keyDirectoryPathOrg2 = path.resolve(
);
// Path to org2 user certificate.
export const certPathOrg2 = path.resolve(
export const certDirectoryPathOrg2 = path.resolve(
cryptoPathOrg2,
'users',
'User1@org2.example.com',
'msp',
'signcerts',
'cert.pem'
'signcerts'
);
// Path to org2 peer tls certificate.
@ -112,17 +110,22 @@ export async function newGrpcConnection(
}
export async function newIdentity(
certPath: string,
certDirectoryPath: string,
mspId: string
): Promise<Identity> {
const certPath = await getFirstDirFileName(certDirectoryPath);
const credentials = await fs.readFile(certPath);
return { mspId, credentials };
}
export async function newSigner(keyDirectoryPath: string): Promise<Signer> {
const files = await fs.readdir(keyDirectoryPath);
const keyPath = path.resolve(keyDirectoryPath, files[0]);
const keyPath = await getFirstDirFileName(keyDirectoryPath);
const privateKeyPem = await fs.readFile(keyPath);
const privateKey = crypto.createPrivateKey(privateKeyPem);
return signers.newPrivateKeySigner(privateKey);
}
async function getFirstDirFileName(dirPath: string): Promise<string> {
const files = await fs.readdir(dirPath);
return path.join(dirPath, files[0]);
}

View file

@ -6,7 +6,7 @@
import { connect } from '@hyperledger/fabric-gateway';
import { newGrpcConnection, newIdentity, newSigner, tlsCertPathOrg1, peerEndpointOrg1, peerNameOrg1, certPathOrg1, mspIdOrg1, keyDirectoryPathOrg1, tlsCertPathOrg2, peerEndpointOrg2, peerNameOrg2, certPathOrg2, mspIdOrg2, keyDirectoryPathOrg2 } from './connect';
import { newGrpcConnection, newIdentity, newSigner, tlsCertPathOrg1, peerEndpointOrg1, peerNameOrg1, certDirectoryPathOrg1, mspIdOrg1, keyDirectoryPathOrg1, tlsCertPathOrg2, peerEndpointOrg2, peerNameOrg2, certDirectoryPathOrg2, mspIdOrg2, keyDirectoryPathOrg2 } from './connect';
import { ContractWrapper } from './contractWrapper';
import { RED, RESET } from './utils';
@ -28,7 +28,7 @@ async function main(): Promise<void> {
const gatewayOrg1 = connect({
client: clientOrg1,
identity: await newIdentity(certPathOrg1, mspIdOrg1),
identity: await newIdentity(certDirectoryPathOrg1, mspIdOrg1),
signer: await newSigner(keyDirectoryPathOrg1),
});
@ -41,7 +41,7 @@ async function main(): Promise<void> {
const gatewayOrg2 = connect({
client: clientOrg2,
identity: await newIdentity(certPathOrg2, mspIdOrg2),
identity: await newIdentity(certDirectoryPathOrg2, mspIdOrg2),
signer: await newSigner(keyDirectoryPathOrg2),
});

View file

@ -21,7 +21,7 @@ export const cryptoPathOrg1 = path.resolve(__dirname, '..', '..', '..', 'test-ne
export const keyDirectoryPathOrg1 = path.resolve(cryptoPathOrg1, 'users', 'User1@org1.example.com', 'msp', 'keystore');
// Path to user certificate.
export const certPathOrg1 = path.resolve(cryptoPathOrg1, 'users', 'User1@org1.example.com', 'msp', 'signcerts', 'cert.pem');
export const certDirectoryPathOrg1 = path.resolve(cryptoPathOrg1, 'users', 'User1@org1.example.com', 'msp', 'signcerts');
// Path to peer tls certificate.
export const tlsCertPathOrg1 = path.resolve(cryptoPathOrg1, 'peers', 'peer0.org1.example.com', 'tls', 'ca.crt');
@ -48,13 +48,12 @@ export const keyDirectoryPathOrg2 = path.resolve(
);
// Path to org2 user certificate.
export const certPathOrg2 = path.resolve(
export const certDirectoryPathOrg2 = path.resolve(
cryptoPathOrg2,
'users',
'User1@org2.example.com',
'msp',
'signcerts',
'cert.pem'
'signcerts'
);
// Path to org2 peer tls certificate.
@ -89,15 +88,20 @@ export async function newGrpcConnection(
});
}
export async function newIdentity(certPath: string, mspId: string): Promise<Identity> {
export async function newIdentity(certDirectoryPath: string, mspId: string): Promise<Identity> {
const certPath = await getFirstDirFileName(certDirectoryPath);
const credentials = await fs.readFile(certPath);
return { mspId, credentials };
}
export async function newSigner(keyDirectoryPath: string): Promise<Signer> {
const files = await fs.readdir(keyDirectoryPath);
const keyPath = path.resolve(keyDirectoryPath, files[0]);
const keyPath = await getFirstDirFileName(keyDirectoryPath);
const privateKeyPem = await fs.readFile(keyPath);
const privateKey = crypto.createPrivateKey(privateKeyPem);
return signers.newPrivateKeySigner(privateKey);
}
async function getFirstDirFileName(dirPath: string): Promise<string> {
const files = await fs.readdir(dirPath);
return path.join(dirPath, files[0]);
}

View file

@ -28,7 +28,7 @@ export CHAINCODE_NAME=${TEST_NETWORK_CHAINCODE_NAME:-asset-transfer-basic}
export MSP_ID=${MSP_ID:-Org1MSP}
export CRYPTO_PATH=${CRYPTO_PATH:-../../test-network-k8s/build/channel-msp/peerOrganizations/org1}
export KEY_DIRECTORY_PATH=${KEY_DIRECTORY_PATH:-../../test-network-k8s/build/enrollments/org1/users/org1admin/msp/keystore}
export CERT_PATH=${CERT_PATH:-../../test-network-k8s/build/enrollments/org1/users/org1admin/msp/signcerts/cert.pem}
export CERT_DIRECTORY_PATH=${CERT_DIRECTORY_PATH:-../../test-network-k8s/build/enrollments/org1/users/org1admin/msp/signcerts}
export TLS_CERT_PATH=${TLS_CERT_PATH:-../../test-network-k8s/build/channel-msp/peerOrganizations/org1/msp/tlscacerts/tlsca-signcert.pem}
export PEER_ENDPOINT=${PEER_ENDPOINT:-org1-peer1.localho.st:443}
export PEER_HOST_ALIAS=${PEER_HOST_ALIAS:-org1-peer1.localho.st}