Skip to content

Commit

Permalink
Read first client cert from cert directory
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
bestbeforetoday authored and denyeart committed Mar 4, 2024
1 parent db86460 commit a5eea8c
Show file tree
Hide file tree
Showing 11 changed files with 146 additions and 96 deletions.
73 changes: 44 additions & 29 deletions asset-transfer-basic/application-gateway-go/assetTransfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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))
}
Expand All @@ -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) {
Expand Down Expand Up @@ -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))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -84,21 +84,21 @@ private static ManagedChannel newGrpcConnection() throws IOException {
}

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();
}
}
Expand Down
15 changes: 10 additions & 5 deletions asset-transfer-basic/application-gateway-typescript/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'));
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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}`);
Expand Down
39 changes: 29 additions & 10 deletions asset-transfer-events/application-gateway-go/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,21 @@ 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"
)

// 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)
}
Expand All @@ -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)
}
Expand All @@ -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))
}
Expand All @@ -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]))
}
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -50,22 +50,21 @@ public static ManagedChannel newGrpcConnection() throws IOException {
}

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);
try (var keyReader = Files.newBufferedReader(getFirstFilePath(keyDirPath))) {
var privateKey = Identities.readPrivateKey(keyReader);
return Signers.newPrivateKeySigner(privateKey);
}
}

private static Path getPrivateKeyPath() throws IOException {
try (var keyFiles = Files.list(keyDirPath)) {
private static Path getFirstFilePath(Path dirPath) throws IOException {
try (var keyFiles = Files.list(dirPath)) {
return keyFiles.findFirst().orElseThrow();
}
}
}
}}
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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]);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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),
});

Expand All @@ -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),
});

Expand Down
Loading

0 comments on commit a5eea8c

Please sign in to comment.