msolefonte
msolefonte

Reputation: 303

TLS handshake fails when raft mode is enabled

I had a running Hyperledger Fabric network with TLS Enabled and Kafka consensus. Now, I have been trying to move to Raft and I am always getting this message in the orderers: TLS handshake failed with error tls: first record does not look like a TLS handshake server=Orderer remoteaddress=ÌP:PORT. As I said, TLS was perfectly working before the changes.

Now I am going to show you what I do related to RAFT and TLS Connections. First of all, I modify the configtx.yaml file, exactly the section related to the Ordering Service.

Section of configtx.yaml

Orderer: &OrdererDefaults
  OrdererType: etcdraft
  Addresses:
  - orderer0.org1:7050
  - orderer0.org2:7050
  - orderer0.org3:7050
  EtcdRaft:
    Consenters:
    - Host: orderer0.org1
      Port: 7050
      ClientTLSCert: /data/org1/orderers/orderer0/tls/client.crt
      ServerTLSCert: /data/org1/orderers/orderer0/tls/server.crt
    - Host: orderer0.org2
      Port: 7050
      ClientTLSCert: /data/org2/orderers/orderer0/tls/client.crt
      ServerTLSCert: /data/org2/orderers/orderer0/tls/server.crt
    - Host: orderer0.org3
      Port: 7050
      ClientTLSCert: /data/org3/orderers/orderer0/tls/client.crt
      ServerTLSCert: /data/org3/orderers/orderer0/tls/server.crt
  Organizations:
  - *org1
  - *org2
  - *org3
  Policies:
    Readers:
      Type: ImplicitMeta
      Rule: "ANY Readers"
    Writers:
      Type: ImplicitMeta
      Rule: "ANY Writers"
    Admins:
      Type: ImplicitMeta
      Rule: "MAJORITY Admins"
    BlockValidation:
      Type: ImplicitMeta
      Rule: "ANY Writers"
  Capabilities:
    <<: *OrdererCapabilities

As can be seen, TLS Client and Server certs from every organizaion orderer are required, so I generate them in each orderer container and upload it to a MinIO server I use to share.

echo "[INFO] Generating Client TLS Key and Certificate..."
fabric-ca-client enroll -d --enrollment.profile tls -u ${ENROLLMENT_URL} -M /tmp/tls --csr.hosts ${ORDERER_HOST}

echo "[INFO] Uploading Client TLS Certificate to Minio"
python3 /scripts/minio_upload.py --url ${STORAGE_URL} --access-key ${STORAGE_ACCESS_KEY} --secret-key ${STORAGE_SECRET_KEY} --bucket-name ${ORG} --local-path ${ORDERER_GENERAL_TLS_CLIENTCERT_FILE} --remote-path orderers/${ORDERER_NAME}/tls/$(basename ${ORDERER_GENERAL_TLS_CLIENTCERT_FILE})
echo "[INFO] Client TLS Certificate uploaded"
echo "[INFO] Enrolling orderer..."
fabric-ca-client enroll -d --enrollment.profile tls -u ${ENROLLMENT_URL} -M /tmp/tls --csr.hosts ${ORDERER_HOST}

echo "[INFO] Uploading Server TLS Certificate to Minio"
python3 /scripts/minio_upload.py --url ${STORAGE_URL} --access-key ${STORAGE_ACCESS_KEY} --secret-key ${STORAGE_SECRET_KEY} --bucket-name ${ORG} --local-path ${ORDERER_GENERAL_TLS_CERTIFICATE} --remote-path orderers/${ORDERER_NAME}/tls/$(basename ${ORDERER_GENERAL_TLS_CERTIFICATE})
echo "[INFO] Server TLS Certificate uploaded"

Once each orderer has generated and uploaded its certificates I run a new container, which I call genesis, where I download configtx.yaml, all the orderers certs (to the paths defined in configtx.yaml) and other things to generate genesis block, channel tx and anchor peer updates. After that, in each orderer, I also download all the orderers certs (do not know if this is required) to the same paths and, of course, copy the genesis block.

In all the orderers I have set to true ORDERER_GENERAL_TLS_CLIENTAUTHREQUIRED and ORDERER_GENERAL_TLS_ENABLED. As an instance, this is the TLS Configuration of orderer0.org1.

env:
- name: ORDERER_GENERAL_TLS_CERTIFICATE
  value: /etc/hyperledger/orderer/tls/server.crt
- name: ORDERER_GENERAL_TLS_CLIENTAUTHREQUIRED
  value: "false"
- name: ORDERER_GENERAL_TLS_CLIENTCERT_FILE  # This is exposed for TLS connections
  value: /shared-storage/tls/orderer0/client.crt
- name: ORDERER_GENERAL_TLS_CLIENTKEY_FILE  # This is exposed for TLS connections
  value: /shared-storage/tls/orderer0/client.key
- name: ORDERER_GENERAL_TLS_CLIENTROOTCAS  # Has to be the same that FABRIC_CA_CLIENT_TLS_CERTFILES
  value: '[/shared-storage/org1/ca-chain.pem]'
- name: ORDERER_GENERAL_TLS_ENABLED
  value: "true"
- name: ORDERER_GENERAL_TLS_PRIVATEKEY
  value: /etc/hyperledger/orderer/tls/server.key
- name: ORDERER_GENERAL_TLS_ROOTCAS  # Has to be the same that FABRIC_CA_CLIENT_TLS_CERTFILES
  value: '[/shared-storage/org1/ca-chain.pem]'

What am I missing? Where is the problem? Thank you very much.

Upvotes: 2

Views: 885

Answers (2)

kekomal
kekomal

Reputation: 2200

EDITED

You are missing these environment variables for your orderer:

      - ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/shared-storage/tls/orderer0/client.crt
      - ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/shared-storage/tls/orderer0/client.key
      # I find strange you use org1 CA in your conf, but I trust you...
      - ORDERER_GENERAL_CLUSTER_ROOTCAS=[/shared-storage/org1/ca-chain.pem]

Upvotes: 3

A. Nonymous
A. Nonymous

Reputation: 1

The error message 'first record does not look like a TLS handshake' indicates that you have a 'client' trying to open a plain (i.e. non-TLS) connection. Make sure all connections are set up to use TLS in all kind of 'clients' (i.e. other orderers, peers, client applications using sdk, etc.).

Upvotes: 0

Related Questions