Skip to content

Commit

Permalink
Include TLS configuration in code examples (#693)
Browse files Browse the repository at this point in the history
For simplicity the code examples in the API documentation created insecure gRPC connections. This led to some confusion for users when the code examples did not work with a Fabric network configured for TLS, which is the typical Fabric configuration.

This change updates the example code snippets in the API documentation to include explicit TLS configuration of the gRPC connection.

Signed-off-by: Mark S. Lewis <Mark.S.Lewis@outlook.com>
  • Loading branch information
bestbeforetoday committed Mar 15, 2024
1 parent abb5dc2 commit 4794168
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 37 deletions.
13 changes: 4 additions & 9 deletions .editorconfig
Expand Up @@ -6,22 +6,17 @@ trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
max_line_length = 120

[*.{js,ts}]
indent_style = space
indent_size = 4

[Makefile]
indent_style = tab

[*.{yaml,yml}]
indent_style = space
indent_size = 2

[*.java]
indent_style = space
indent_size = 4
[*.html]
indent_size = 2

[*.json]
indent_style = space
indent_size = 4
[*.md]
indent_size = 2
8 changes: 4 additions & 4 deletions java/README.md
Expand Up @@ -28,7 +28,7 @@ Add the following dependency to your project's `pom.xml` file:
<dependency>
<groupId>org.hyperledger.fabric</groupId>
<artifactId>fabric-gateway</artifactId>
<version>1.4.0</version>
<version>1.5.0</version>
</dependency>
```

Expand All @@ -38,7 +38,7 @@ A suitable gRPC channel service provider must also be specified (as described in
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.59.0</version>
<version>1.62.2</version>
<scope>runtime</scope>
</dependency>
```
Expand All @@ -48,13 +48,13 @@ A suitable gRPC channel service provider must also be specified (as described in
Add the following dependency to your project's `build.gradle` file:

```groovy
implementation 'org.hyperledger.fabric:fabric-gateway:1.4.0'
implementation 'org.hyperledger.fabric:fabric-gateway:1.5.0'
```

A suitable gRPC channel service provider must also be specified (as described in the [gRPC security documentation](https://github.com/grpc/grpc-java/blob/master/SECURITY.md#transport-security-tls)), such as:

```groovy
runtimeOnly 'io.grpc:grpc-netty-shaded:1.59.0'
runtimeOnly 'io.grpc:grpc-netty-shaded:1.62.2'
```

## Compatibility
Expand Down
47 changes: 30 additions & 17 deletions java/src/main/javadoc/overview.html
@@ -1,27 +1,37 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>API Overview</title>
</head>
<body>
<p>The Fabric Gateway SDK allows applications to interact with a Fabric blockchain network. It provides a simple API
to submit transactions to a ledger or query the contents of a ledger with minimal code. The Gateway SDK implements
the Fabric programming model as described in the
<a href="https://hyperledger-fabric.readthedocs.io/en/latest/write_first_app.html">Running a Fabric Application</a>
tutorial of the Fabric documentation.</p>
<p>
The Fabric Gateway SDK allows applications to interact with a Fabric blockchain network. It provides a simple API
to submit transactions to a ledger or query the contents of a ledger with minimal code. The Gateway SDK implements
the Fabric programming model as described in the
<a href="https://hyperledger-fabric.readthedocs.io/en/latest/write_first_app.html">
Running a Fabric Application
</a>
tutorial of the Fabric documentation.
</p>

<p>Client applications interact with the blockchain network using a Fabric Gateway. A session for a given client
identity is established by building and connecting to a Fabric Gateway using a gRPC connection to the Gateway
endpoint, client identity, and client signing implementation. The returned <code>Gateway</code> enables interaction
with any of the blockchain <code>Networks</code> (channels) accessible through the Fabric Gateway. This in turn
provides access to Smart <code>Contracts</code> within chaincode deployed to that blockchain network, and to which
transactions can be submitted or queries can be evaluated.
<p>
Client applications interact with the blockchain network using a Fabric Gateway. A session for a given client
identity is established by building and connecting to a Fabric Gateway using a gRPC connection to the Gateway
endpoint, client identity, and client signing implementation. The returned
<code>Gateway</code> enables interaction with any of the blockchain <code>Networks</code> (channels) accessible
through the Fabric Gateway. This in turn provides access to Smart <code>Contracts</code> within chaincode deployed
to that blockchain network, and to which transactions can be submitted or queries can be evaluated.
</p>

<p>gRPC connections to a Fabric Gateway may be shared by all <code>Gateway</code> instances interacting with that
Fabric Gateway.</p>
<p>
gRPC connections to a Fabric Gateway may be shared by all <code>Gateway</code> instances interacting with that
Fabric Gateway.
</p>

<p>The following shows a complete code sample of how to connect to a fabric network, submit a transaction and query
the ledger state using an instantiated smart contract.</p>
<p>
The following shows a complete code sample of how to connect to a fabric network, submit a transaction and query
the ledger state using an instantiated smart contract.
</p>

<pre><code>
import io.grpc.Grpc;
Expand All @@ -39,7 +49,10 @@
PrivateKey privateKey = Identities.readPrivateKey(keyReader);
Signer signer = Signers.newPrivateKeySigner(privateKey);

ManagedChannel grpcChannel = Grpc.newChannelBuilder("gateway.example.org:1337", TlsChannelCredentials.create())
ChannelCredentials tlsCredentials = TlsChannelCredentials.newBuilder()
.trustManager(Paths.get(tlsRootCertPath).toFile())
.build();
ManagedChannel grpcChannel = Grpc.newChannelBuilder("gateway.example.org:1337", tlsCredentials)
.build();

Gateway.Builder builder = Gateway.newInstance()
Expand Down
11 changes: 6 additions & 5 deletions node/src/README.md
@@ -1,6 +1,6 @@
# Overview

The *fabric-gateway* package enables Node.js developers to build client applications using the Hyperledger Fabric programming model as described in the [Running a Fabric Application](https://hyperledger-fabric.readthedocs.io/en/latest/write_first_app.html) tutorial of the Fabric documentation.
The _fabric-gateway_ package enables Node.js developers to build client applications using the Hyperledger Fabric programming model as described in the [Running a Fabric Application](https://hyperledger-fabric.readthedocs.io/en/latest/write_first_app.html) tutorial of the Fabric documentation.

[TypeScript](http://www.typescriptlang.org/) definitions are included in this package.

Expand All @@ -14,9 +14,9 @@ gRPC connections to a Fabric Gateway may be shared by all `Gateway` instances in

The following complete example shows how to connect to a Fabric network, submit a transaction and query the ledger state using an instantiated smart contract.

```typescript
```TypeScript
import * as grpc from '@grpc/grpc-js';
import * as crypto from 'crypto';
import * as crypto from 'node:crypto';
import { connect, Identity, signers } from '@hyperledger/fabric-gateway';
import { promises as fs } from 'fs';
import { TextDecoder } from 'util';
Expand All @@ -31,7 +31,8 @@ async function main(): Promise<void> {
const privateKey = crypto.createPrivateKey(privateKeyPem);
const signer = signers.newPrivateKeySigner(privateKey);

const client = new grpc.Client('gateway.example.org:1337', grpc.credentials.createInsecure());
const tlsRootCert = await fs.readFile('path/to/tlsRootCertificate.pem');
const client = new grpc.Client('gateway.example.org:1337', grpc.credentials.createSsl(tlsRootCert));

const gateway = connect({ identity, signer, client });
try {
Expand All @@ -45,7 +46,7 @@ async function main(): Promise<void> {
console.log('Get result:', utf8Decoder.decode(getResult));
} finally {
gateway.close();
client.close()
client.close();
}
}

Expand Down
20 changes: 18 additions & 2 deletions pkg/client/example_test.go
Expand Up @@ -7,18 +7,19 @@ SPDX-License-Identifier: Apache-2.0
package client_test

import (
"crypto/x509"
"fmt"
"os"

"github.com/hyperledger/fabric-gateway/pkg/client"
"github.com/hyperledger/fabric-gateway/pkg/identity"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/credentials"
)

func Example() {
// Create gRPC client connection, which should be shared by all gateway connections to this endpoint.
clientConnection, err := grpc.Dial("gateway.example.org:1337", grpc.WithTransportCredentials(insecure.NewCredentials()))
clientConnection, err := NewGrpcConnection()
panicOnError(err)
defer clientConnection.Close()

Expand Down Expand Up @@ -46,6 +47,21 @@ func Example() {
fmt.Printf("Evaluate result: %s", string(evaluateResult))
}

// NewGrpcConnection creates a new gRPC client connection
func NewGrpcConnection() (*grpc.ClientConn, error) {
tlsCertificatePEM, err := os.ReadFile("tlsRootCertificate.pem")
panicOnError(err)

tlsCertificate, err := identity.CertificateFromPEM(tlsCertificatePEM)
panicOnError(err)

certPool := x509.NewCertPool()
certPool.AddCert(tlsCertificate)
transportCredentials := credentials.NewClientTLSFromCert(certPool, "")

return grpc.Dial("gateway.example.org:1337", grpc.WithTransportCredentials(transportCredentials))
}

// NewIdentity creates a client identity for this Gateway connection using an X.509 certificate.
func NewIdentity() *identity.X509Identity {
certificatePEM, err := os.ReadFile("certificate.pem")
Expand Down

0 comments on commit 4794168

Please sign in to comment.