I see there are a lot of questions about this error, I have seen this solution Raft bad format but I doubled checked and the folders are right and the certs are in there, I also looked at Sans problem but for what I understand I don't need Sans when using Raft (I may be wrong). I think my problem its because I'm not handling the intermediate certificates correctly and I'm getting the error both creating a channel and in the Raft consensus.
So here is what I've done so far:
I created my genesis block using a configtx.yaml and this msp folder structure:
configtx.yaml
Organizations:
- &ordererOrg
Name: orderer
ID: orderer
MSPDir: /crypto/msp
Policies:
Readers:
Type: Signature
Rule: "OR('orderer.member')"
Writers:
Type: Signature
Rule: "OR('orderer.member')"
Admins:
Type: Signature
Rule: "OR('orderer.admin')"
Capabilities:
Channel: &ChannelCapabilities
V1_4_3: true
Orderer: &OrdererCapabilities
V1_4_2: true
Application: &ApplicationCapabilities
V1_4_2: true
Application: &ApplicationDefaults
Organizations:
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
Capabilities:
<<: *ApplicationCapabilities
Orderer: &OrdererDefaults
OrdererType: solo
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 10
AbsoluteMaxBytes: 99 MB
PreferredMaxBytes: 512 KB
Kafka:
Brokers:
- 127.0.0.1:9092
Organizations:
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"
Channel: &ChannelDefaults
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
Capabilities:
<<: *ChannelCapabilities
Profiles:
SampleEtcdRaftProfile:
<<: *ChannelDefaults
Capabilities:
<<: *ChannelCapabilities
Orderer:
<<: *OrdererDefaults
OrdererType: etcdraft
Addresses:
- orderer1.xxxx.eastus.aksapp.io:443
- orderer2.xxxx.eastus.aksapp.io:443
Organizations:
- *ordererOrg
EtcdRaft:
Consenters:
- Host: orderer1
Port: 7050
ClientTLSCert: /crypto/orderers/orderer1/tls/server.crt
ServerTLSCert: /crypto/orderers/orderer1/tls/server.crt
- Host: orderer2
Port: 7050
ClientTLSCert: /crypto/orderers/orderer2/tls/server.crt
ServerTLSCert: /crypto/orderers/orderer2/tls/server.crt
Capabilities:
<<: *OrdererCapabilities
Application:
<<: *ApplicationDefaults
Organizations:
- <<: *ordererOrg
Consortiums:
SampleConsortium:
Organizations:
- *ordererOrg
MSP folder structure:
+ /crypto
configtx.yaml
+ msp
+ cacerts > ca.crt
+ tlscacerts > ca.crt
+ intermediatecerts > intermediate.crt
+ tlsintermediatecerts > intermediate.crt
+ admincerts > admin.crt
+ orderers
+ orderer1/tls > server.crt
+ orderer2/tls > server.crt
I created my genesis block using this:
configtxgen -profile SampleEtcdRaftProfile -outputBlock genesis.block -channelID mychannel
Now here I have a doubt inside my orderer the msp structure is like this:
+ /var/hyperledger/orderer
genesis.block
+ msp
+ cacerts > ca.crt
+ intermediatecerts > intermediate.crt
+ admincerts > admin.crt
+ signcerts > cert.pem
+ keystore > key.pem
+ tls
server.crt
server.key
ca.crt
intermediate.crt
And these are my env variables:
ORDERER_GENERAL_TLS_ENABLED=true
ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
ORDERER_GENERAL_TLS_CLIENTROOTCAS=/var/hyperledger/orderer/tls/ca.crt
ORDERER_GENERAL_TLS_CLIENTAUTHREQUIRED=false
ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key
ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt
ORDERER_GENERAL_CLUSTER_ROOTCAS=/var/hyperledger/orderer/tls/ca.crt
I'm not sure why the structure is different and the tls files are somewhere else but I am copying the configuration from the azure hyperledger template That I have already used successfuly.
Now my orderers are running but orderer1 keeps starting a new election and orderer 2 becomes precandidate and finally fails with a TLS handshake error.
These are the error logs in orderer2:
2021-03-23 22:15:21.969 UTC [orderer.consensus.etcdraft] Step -> INFO f96 2 is starting a new election at term 1 channel=canalenergia node=2
2021-03-23 22:15:21.969 UTC [orderer.consensus.etcdraft] becomePreCandidate -> INFO f97 2 became pre-candidate at term 1 channel=canalenergia node=2
2021-03-23 22:15:21.969 UTC [orderer.consensus.etcdraft] poll -> INFO f98 2 received MsgPreVoteResp from 2 at term 1 channel=canalenergia node=2
2021-03-23 22:15:21.969 UTC [orderer.consensus.etcdraft] campaign -> INFO f99 2 [logterm: 1, index: 2] sent MsgPreVote request to 1 at term 1 channel=canalenergia node=2
2021-03-23 22:15:26.673 UTC [core.comm] ServerHandshake -> ERRO f9a TLS handshake failed with error remote error: tls: bad certificate server=Orderer remoteaddress=x.x.x.x:45472
I tried deleting intermediate.crt and mixing ca.crt and intermediate.crt into one file in ca.crt in the tls folder of the orderer like this:
-----BEGIN CERTIFICATE-----
ROOTCERTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
INTERMEDIATExxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-----END CERTIFICATE-----
But it didn't work either.
I tried openssl verify -CAfile chain.crt orderer1-tls.crt and returns OK.
This is what happens when I try to create a new channel:
peer channel create -o orderer1.xxxx.eastus.aksapp.io -c testchannel -f ./channel.tx --tls --cafile /var/hyperledger/peer/msp/tlscacerts/ca.crt --clientauth --certfile /var/hyperledger/peer/tls/cert.pem --keyfile /var/hyperledger/peer/tls/key.pem
2021-03-24 00:04:40.331 UTC [comm.tls] ClientHandshake -> ERRO 001 Client TLS handshake failed after 939.077µs with error: EOF remoteaddress=x.x.x.x:443
I tested my urls with telnet and they are ok.
I created my certificates using openSSL but I don't see anything wrong in them, the only difference is that they aren't signed by a fabric-ca but by an intermediate CA from a big company.
I have double checked all the values but I guess orderer wouldn't even be running if they weren't right and followed this script from azure for the creation of the genesis block only adding the intermediate info.
Any advice would be great.
Thanks
UPDATE:
I activated the debug logs with this variable:
FABRIC_LOGGING_SPEC="grpc=debug:info"
And found the problem is this:
transport: authentication handshake failed: x509: certificate is not valid for any names, but wanted to match orderer1
My certificate has this subject:
CN=orderer1-tls@blockchain.company.com,O=Company,L=CITY,ST=STATE,C=US
Now, I don't understand why its telling me it doesn't have a name, I though the CN orderer1-tls@blockchain.company.com was the name, and, also, where did I tell the orderer that the name to search is "orderer1"?
UPDATE 2:
I changed my TLS certificates to CN=orderer.company.com and then the error was this:
x509: certificate is valid for orderer1.company.com, not orderer1
So as 李可以 says, the orderer is expecting the hostname in the certificate CN and my hostname is orderer1 so I changed it to that.
Now I'm getting a new error:
UTC [comm.grpc.server] 1 -> INFO 118 streaming call completed grpc.service=orderer.Cluster grpc.method=Step grpc.peer_address=x.x.x.x:39424 error="no TLS certificate sent" grpc.code=Unknown grpc.call_duration=161.713µs
I guess This is a new error so I'm going to open a new question. thanks!