问题描述
在查询分类帐时遇到问题。这是我们网络的布局方式。 corp 网络内的 kubernetes 集群上有 2 个组织,网络内 azure vm 上的 docker swarm 上也有一个。 azure vm 节点和 k8s 集群节点通过 Nginx 服务器相互通信。现在这个精心设置背后的原因是因为我们的供应链用例需要来自不同公司的合作伙伴加入我们的网络。因此,为了模拟 corp 网络之外的外部合作伙伴,我们使用 azure vm。由于我们计划生产实施,我们无法使用 Fabric 加密配置生成的证书,并使用我们公司的中间证书和根证书颁发新证书。现在,此网络设置上安装了链码,启用了背书策略,可在所有 3 个节点上完美运行。我们使用的是 Fabric 2.3.0
现在我面临的第一个问题是要在 connection.json 文件中使用的 TLS 证书。这是通过按照 SO post here 中的描述链接证书来解决的。当前的问题是 nodejs 代码能够连接到组织,但无法执行任何读取或写入操作。在下面的 JS 代码中,如果我取消注释 channel.getPeer() 响应的控制台日志,它会正确打印整个对等对象。
这是我的 connection.json。所有 10.100.xx.xx ips 都是 k8s 集群中的 pods,public.ip.address 是 Nginx 服务器的地址
{
"name": "byfn","version": "1.0.0","client": {
"organization": "ORG2MSP","connection": {
"timeout": {
"peer": {
"endorser": "10000"
},"orderer": "10000"
}
}
},"channels": {
"supplychain": {
"orderers": [
"ord1.orderers.org1.com","ord2.orderers.org1.com","ord3.orderers.org1.com"
],"peers": {
"peer1.peers.org1.com": {
"endorsingPeer": true,"chaincodeQuery": true,"ledgerQuery": true,"eventSource": true
},"peer1.peers.org3.com": {
"endorsingPeer": true,"peer1.peers.org2.com": {
"endorsingPeer": true,"eventSource": true
}
}
}
},"organizations": {
"ORG2MSP": {
"mspid": "ORG2MSP","peers": [
"peer1.peers.org2.com","peer2.peers.org2.com"
]
}
},"orderers": {
"ord1.orderers.org1.com": {
"url": "grpcs://10.100.xxx.xxx:7050","grpcoptions": {
"ssl-target-name-override": "ord1.orderers.org1.com","request-timeout": 12000
},"tlsCACerts": {
"path": "temp.pem"
}
},"ord2.orderers.org1.com": {
"url": "grpcs://10.100.xxx.xxx:7050","grpcoptions": {
"ssl-target-name-override": "ord2.orderers.org1.com","ord3.orderers.org1.com": {
"url": "grpcs://10.100.xxx.xxx:7050","grpcoptions": {
"ssl-target-name-override": "ord3.orderers.org1.com","tlsCACerts": {
"path": "temp.pem"
}
}
},"peers": {
"peer1.peers.org1.com": {
"url": "grpcs://10.100.xxx.xxx:7051","grpcoptions": {
"ssl-target-name-override": "peer1.peers.org1.com","request-timeout": 12000,"grpc.keepalive_time_ms": 600000
},"peer1.peers.org3.com": {
"url": "grpcs://public.ip.address:7051","grpcoptions": {
"ssl-target-name-override": "peer1.peers.org3.com","peer1.peers.org2.com": {
"url": "grpcs://10.100.xxx.xxx:7051","grpcoptions": {
"ssl-target-name-override": "peer1.peers.org2.com","tlsCACerts": {
"path": "temp.pem"
}
}
}
}
这是我的代码
'use strict';
const { Wallets,Gateway } = require('fabric-network');
const fs = require('fs');
const path = require('path');
const ccpPath = path.resolve(__dirname,'connection.json');
const ccpJSON = fs.readFileSync(ccpPath,'utf8');
const ccp = JSON.parse(ccpJSON);
async function main(){
try {
// const walletPath = path.join(process.cwd(),'wallet');
const wallet = await Wallets.newFileSystemWallet('wallet');
// console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userExists = await wallet.get('usernew');
const tlsExists = await wallet.get('tlsid');
if (!userExists) {
console.log('An identity for the user "usernew" does not exist in the wallet');
return;
}
if (!tlsExists) {
console.log('An identity for the user "tls" does not exist in the wallet');
return;
}
console.log("Here");
// Create a new gateway for connecting to our peer node.
const gateway = new Gateway();
await gateway.connect(ccp,{ wallet,identity: 'usernew',discovery: { enabled: false,asLocalhost: false },clientTlsIdentity: 'tlsid' });
console.log("Here1");
// Get the network (channel) our contract is deployed to.
const network = await gateway.getNetwork('supplychain');
console.log("Here2");
//Get the channel object to fetch out peers
const channel = network.getChannel();
console.log("Here3");
//Get peers for endorsement
//channel.getEndorsers();
const org1Peer = channel.getPeer('peer1.peers.org1.com');
//console.log(org1Peer);
const org2Peer = channel.getPeer('peer1.peers.org2.com');
//console.log(org2Peer);
const org3Peer = channel.getPeer('peer1.peers.org3.com');
//console.log(org3Peer);
// All the above logs print correct information
// Get the contract from the network.
const contract = network.getContract('mycontract');
const result = await contract.evaluateTransaction('queryAllObjects');
console.log(`Transaction has been evaluated,result is: ${result.toString()}`);
} catch (error) {
console.error(`Failed to evaluate transaction: ${error}`);
}
}
main()
这是加密文件夹树
C:.
├───peers.org1.com
│ └───users
│ ├───Admin@peers.org1.com
│ │ ├───msp
│ │ │ ├───admincerts
│ │ │ ├───cacerts
│ │ │ ├───intermediatecerts
│ │ │ ├───keystore
│ │ │ ├───signcerts
│ │ │ ├───tlscacerts
│ │ │ └───tlsintermediatecerts
│ │ └───tls
│ └───User1@peers.org1.com
│ ├───msp
│ │ ├───admincerts
│ │ ├───cacerts
│ │ ├───intermediatecerts
│ │ ├───keystore
│ │ ├───signcerts
│ │ ├───tlscacerts
│ │ └───tlsintermediatecerts
│ └───tls
├───peers.org2.com
│ └───users
│ ├───Admin@peers.org2.com
│ │ ├───msp
│ │ │ ├───admincerts
│ │ │ ├───cacerts
│ │ │ ├───intermediatecerts
│ │ │ ├───keystore
│ │ │ ├───signcerts
│ │ │ ├───tlscacerts
│ │ │ └───tlsintermediatecerts
│ │ └───tls
│ └───User1@peers.org2.com
│ ├───msp
│ │ ├───admincerts
│ │ ├───cacerts
│ │ ├───intermediatecerts
│ │ ├───keystore
│ │ ├───signcerts
│ │ ├───tlscacerts
│ │ └───tlsintermediatecerts
│ └───tls
└───peers.org3.com
└───users
├───Admin@peers.org3.com
│ ├───msp
│ │ ├───admincerts
│ │ ├───cacerts
│ │ ├───intermediatecerts
│ │ ├───keystore
│ │ ├───signcerts
│ │ ├───tlscacerts
│ │ └───tlsintermediatecerts
│ └───tls
└───User1@peers.org3.com
├───msp
│ ├───admincerts
│ ├───cacerts
│ ├───intermediatecerts
│ ├───keystore
│ ├───signcerts
│ ├───tlscacerts
│ └───tlsintermediatecerts
└───tls
上面连接文件中使用的 temp.pem 是通过附加如下所示的 ica.pem 和 ca.pem 来准备的。以下是证书查找 Org2 的方式。其他 2 个组织看起来相似。 msp/tlscacerts/ca.pem
Issuer: C=XX,ST=XXXX,L=XXXX,O=MyCompany,OU=cybersecurity,CN=MyCompany Root Certificate Authority 2018
Validity
Not Before: Jul 23 17:07:45 2018 GMT
Not After : Jul 23 17:17:44 2043 GMT
Subject: C=XX,CN=MyCompany Root Certificate Authority
msp/tlsintermediatecerts/ica.pem
Issuer: C=XX,CN=MyCompany Root Certificate Authority 2018
Validity
Not Before: Nov 14 21:26:35 2018 GMT
Not After : Nov 14 21:36:35 2025 GMT
Subject: C=XX,CN=MyCompany Issuing CA 101
tls/server.crt
Issuer: C=XX,CN=MyCompany Issuing CA 101
Validity
Not Before: Jan 18 20:30:30 2021 GMT
Not After : Jan 18 20:30:30 2023 GMT
Subject: C=XX,O=MyCompany Inc.,OU=org2client,CN=*.peers.org2.com
.
.
.
X509v3 Subject Alternative Name:
DNS:*.peers.org2.com
Org2 NodeJs 日志
2021-02-25T10:21:33.736Z - error: [Endorser]: sendProposal[peer1.peers.org2.com] - Received error response from: grpcs://10.100.xxx.xxx:7051 error: Error: 2 UNKNowN: error validating proposal: access denied: channel [supplychain] creator org [ORG2MSP]
2021-02-25T10:21:33.738Z - error: [Endorser]: sendProposal[peer1.peers.org2.com] - rejecting with: Error: 2 UNKNowN: error validating proposal: access denied: channel [supplychain] creator org [ORG2MSP]
2021-02-25T10:21:33.738Z - error: [SingleQueryHandler]: evaluate: message=Query Failed. Errors: ["Error: 2 UNKNowN: error validating proposal: access denied: channel [supplychain] creator org [ORG2MSP]"],stack=FabricError: Query Failed. Errors: ["Error: 2 UNKNowN: error validating proposal: access denied: channel [supplychain] creator org [ORG2MSP]"]
at SingleQueryHandler.evaluate (/fabric23/node_modules/fabric-network/lib/impl/query/singlequeryhandler.js:47:23)
at processticksAndRejections (internal/process/task_queues.js:97:5)
at async Transaction.evaluate (/fabric23/node_modules/fabric-network/lib/transaction.js:276:25)
at async main (/fabric23/test.js:67:25),name=FabricError
Failed to evaluate transaction: FabricError: Query Failed. Errors: ["Error: 2 UNKNowN: error validating proposal: access denied: channel [supplychain] creator org [ORG2MSP]"]
Org2 对等日志
2021-02-25 10:21:33.732 UTC [endorser] Validate -> WARN 08f access denied: creator's signature over the proposal is not valid: The signature is invalid channel=supplychain txID=01bde838 mspID=ORG2MSP
2021-02-25 10:21:33.732 UTC [comm.grpc.server] 1 -> INFO 090 unary call completed grpc.service=protos.Endorser grpc.method=Processproposal grpc.peer_address=172.23.238.200:40928 grpc.peer_subject="CN=*.peers.org3.com,OU=org3client,C=XX" error="error validating proposal: access denied: channel [supplychain] creator org [ORG2MSP]" grpc.code=UnkNown grpc.call_duration=12.335491ms
Org3 对等日志
2021-02-26 13:42:26.081 UTC [gossip.channel] publishStateInfo -> DEBU 6155d8 Empty membership,no one to publish state info to
2021-02-26 13:42:26.493 UTC [core.comm] ServerHandshake -> DEBU 6155d9 Server TLS handshake completed in 49.605106ms server=PeerServer remoteaddress=public.ip.address:291542021-02-26 13:42:26.597 UTC [grpc] InfoDepth -> DEBU 6155da [transport]transport: loopyWriter.run returning. connection error: desc = "transport is closing"
2021-02-26 13:42:26.927 UTC [gossip.channel] publishStateInfo -> DEBU 6155db Empty membership,no one to publish state info to
我还尝试在 azure vm 上的 docker swarm 上部署相同的代码。但是,当我使用 SO post here
中给出的错误证书时,它给出了相同的错误解决方法
您可能会检查的一些要点:
- 您的 org3 的对等服务器 TLS 证书应该有一个替代名称,例如“*.ip.adress”?
- 频道拥有所有 3 个组织,对吗?从 org2 的日志中,我看到“提案的创建者签名无效”
- 检查用户身份“usernew”PKI(不是 TLS)以确保颁发证书的 CA 是通道上的 CA MSP 之一。如果您使用中间 CA,则这些 CA 证书也应在通道中。
最好的问候, 茨维坦