Vlado
Vlado

Reputation: 31

How to configure mutual TLS in Hyperledger Fabric?

In Hyperledger network I have enabled both TLS and CLIENTAUTH (on peers and orderers, not on CA). But when it comes to submitting transactions via fabric-sdk-node libraries I keep getting errors during verification of client's certificates.

I also tried setting TLS client certificates explicitly but no luck. https://fabric-sdk-node.github.io/tutorial-mutual-tls.html

peer / order .yaml

- name: CORE_PEER_TLS_ENABLED
  value: "true"
- name: CORE_PEER_TLS_CERT_FILE
  value: /shared/crypto-config/peerOrganizations/org1.example.com/peers/blockchain-org1peer2.org1.example.com/tls/server.crt
- name: CORE_PEER_TLS_KEY_FILE
  value: /shared/crypto-config/peerOrganizations/org1.example.com/peers/blockchain-org1peer2.org1.example.com/tls/server.key
- name: CORE_PEER_TLS_ROOTCERT_FILE
  value: /shared/crypto-config/peerOrganizations/org1.example.com/peers/blockchain-org1peer2.org1.example.com/tls/ca.crt
- name: CORE_PEER_TLS_CLIENTAUTHREQUIRED
  value: "true"
- name: CORE_PEER_TLS_CLIENTROOTCAS_FILES
  value: /shared/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/ca.crt
- name: CORE_PEER_TLS_CLIENTCERT_FILE
  value: /shared/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/client.crt
- name: CORE_PEER_TLS_CLIENTKEY_FILE
  value: /shared/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/client.key

connection.json

{
    "name": "bam-ticketing-network",
    "version": "1.0.0",
    "client": {
        "organization": "Org1",
        "connection": {
            "timeout": {
                "peer": {
                    "endorser": "300"
                },
                "orderer": "300"
            }
        },
        "credentialStore": {
          "path": "./local_fabric/tmp/hfc-kvs",
          "cryptoStore": {
            "path": "./local_fabric/tmp/hfc-cvs"
          },
          "wallet": "wallet"
        },
        "tlsCerts": {
            "systemCertPool": true,
            "client": {
                "key": {
                    "path": "./local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/client.key"
                },
                "cert": {
                    "path": "./local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/client.crt"
                }
            }
        }
    },
    "channels": {
        "channel1": {
            "orderers": [
                "blockchain-orderer1",
                "blockchain-orderer2",
                "blockchain-orderer3"
            ],
            "peers": {
                "blockchain-org1peer1": {
                    "endorsingPeer": true,
                    "chaincodeQuery": true,
                    "ledgerQuery": true,
                    "eventSource": true
                },
                "blockchain-org1peer2": {
                    "endorsingPeer": true,
                    "chaincodeQuery": true,
                    "ledgerQuery": true,
                    "eventSource": true
                }
            }
        }
    },
    "organizations": {
        "Org1": {
            "mspid": "Org1MSP",
            "peers": [
                "blockchain-org1peer1",
                "blockchain-org1peer2"
            ],
            "certificateAuthorities": [
                "blockchain-ca"
            ],
            "adminPrivateKey": [
                "./local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp/keystore/key.pem"
            ],
            "signedCert": [
                "./local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp/signcerts/[email protected]"
            ]
        }
    },
    "orderers": {
        "blockchain-orderer1": {
            "url": "grpcs://192.168.99.130:31011",
            "grpcOptions": {
                "ssl-target-name-override": "blockchain-orderer1",
                "grpc-max-send-message-length": 4194304
            },
            "tlsCACerts": {
                "path": "./local_fabric/certs/crypto-config/ordererOrganizations/example.com/orderers/blockchain-orderer1.example.com/tls/ca.crt"
            }
        },
        "blockchain-orderer2": {
            "url": "grpcs://192.168.99.130:31012",
            "grpcOptions": {
                "ssl-target-name-override": "blockchain-orderer2",
                "grpc-max-send-message-length": 4194304
            },
            "tlsCACerts": {
                "path": "./local_fabric/certs/crypto-config/ordererOrganizations/example.com/orderers/blockchain-orderer2.example.com/tls/ca.crt"
            }
        },
        "blockchain-orderer3": {
            "url": "grpcs://192.168.99.130:31013",
            "grpcOptions": {
                "ssl-target-name-override": "blockchain-orderer3",
                "grpc-max-send-message-length": 4194304
            },
            "tlsCACerts": {
                "path": "./local_fabric/certs/crypto-config/ordererOrganizations/example.com/orderers/blockchain-orderer3.example.com/tls/ca.crt"
            }
        }
    },
    "peers": {
        "blockchain-org1peer1": {
            "url": "grpcs://192.168.99.130:30110",
            "grpcOptions": {
                "ssl-target-name-override": "blockchain-org1peer1",
                "grpc.keepalive_time_ms": 600000
            },
            "clientKey": { 
                "path": "./local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/client.key"
            },
            "clientCert": {
                "path": "./local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/client.crt"
            },
            "tlsCACerts": {
                "path": "./local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/peers/blockchain-org1peer1.org1.example.com/tls/ca.crt"
            }
        },
        "blockchain-org1peer2": {
            "url": "grpcs://192.168.99.130:30210",
            "grpcOptions": {
                "ssl-target-name-override": "blockchain-org1peer2",
                "grpc.keepalive_time_ms": 600000
            },
            "clientKey": { 
                "path": "./local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/client.key"
            },
            "clientCert": {
                "path": "./local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/client.crt"
            },
            "tlsCACerts": {
                "path": "./local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/peers/blockchain-org1peer2.org1.example.com/tls/ca.crt"
            }
        }
    },
    "certificateAuthorities": {
        "blockchain-ca": {
            "url": "https://192.168.99.130:30054",
            "registrar": {
                "enrollmentID": "admin",
                "enrollmentSecret": "adminpw",
                "profile": "tls"
            },
            "httpOptions": {
                "verify": false
            },
            "tlsCACerts": {
                "path": "./local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem",
                "client": {
                    "key": {
                        "path": "./local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/client.key"
                    },
                    "cert": {
                        "path": "./local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/client.crt"
                    }
                }
            }
        }
    }
}

I keep getting this error:

On peer: ERRO 1587b[0m TLS handshake failed with error tls: failed to verify client's certificate: x509: certificate signed by unknown authority server=PeerServer remoteaddress=172.17.0.1:62440

On nodejs app: ERRO 11347[0m TLS handshake failed with error tls: failed to verify client's certificate: x509: certificate signed by unknown authority server=PeerServer remoteaddress=172.17.0.1:6156

I would expect that fabric client or gateway could provide some option to support mutual TLS or some sample of connection.json.

Upvotes: 2

Views: 2047

Answers (1)

Vlado
Vlado

Reputation: 31

During troubleshooting I have discovered that fabric-client for some reason doesn't load proper certificate for mutual TLS. The loaded certificate content is different from the one sepcified in "tlsCerts" section of client config. (For more details bug report)

Anyhow, I have manage to resolve loading proper certificate with following workaround where I explicitly set this key and certificate to the client:

    const clientKey = fs.readFileSync(path.join(__dirname, './local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/client.key'));
    const clientCert = fs.readFileSync(path.join(__dirname, './local_fabric/certs/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/tls/client.crt'));

    const gateway = new Gateway();
    const caName = ccp.getCertificatAuthoritiesForOrg(orgName)[0];

    const opts = {
        wallet: wallet,
        identity: identityID,
        discovery: {enabled: false, asLocalhost: false},
        clientTlsIdentity: 'tlsId'
    };

    await gateway.connect(ccp.profile, opts);
    //set TLS certs for CLIENTAUTH
    const client = await gateway.getClient();
    client.setTlsClientCertAndKey(Buffer.from(clientCert).toString(), Buffer.from(clientKey).toString());

Upvotes: 1

Related Questions