Hyperledger Fabric - 来自 fabric-ca 的带有 TLS 的外部链代码

Hyperledger Fabric - external chaincode with TLS from fabric-ca

我正在尝试使用新的外部链代码服务功能设置 Hyperledger Fabric。 运行 具有默认配置(无 tls 或对等身份验证)的链代码按预期工作。

我已经阅读了很多关于这个主题的教程,但它们都只为此目的使用自签名证书 - 这不是很有帮助,因为我正在配置生产系统。我想使用我的网络中已经 运行 的证书颁发机构 (fabric-ca-server),并为我的订购者、同行等提供证书。

我的问题是:如何使用我现有的 CA 生成 root_cert 以及 client_cert 和 client_key?必须有一种方法可以使用 fabric-ca-client 来做到这一点。我已经尝试使用我的同行组织的 ca 证书,但那没有用(它似乎不包含链代码服务的主机名)。

感谢您的帮助。

更新:

我现在尝试使用 fabric-ca-client 的 register 和 enroll 命令来注册身份并为自己获取 tls Enrollment-profile。

fabric-ca-client register --caname $CANAME --id.name chaincode --id.secret chainpw --tls.certfiles $certfile --loglevel error
fabric-ca-client enroll -u https://chaincode: chainpw@$CA_HOST_ADDRESS:$nodePort --caname $CANAME -M "$chainDir/msp" --csr.cn diplom-$validK8SHostName  --csr.hosts diplom-$validK8SHostName --tls.certfiles $certfile --loglevel error
fabric-ca-client enroll -u https://chaincode: chainpw@$CA_HOST_ADDRESS:$nodePort --caname $CANAME -M "$chainDir/tls" --enrollment.profile tls --csr.hosts diplom-$validK8SHostName --csr.hosts localhost --tls.certfiles $certfile --loglevel error

我从生成的 tls 目录中取出 /signcerts/cert.pem 并通过 awk 'NF {sub(/\r/, ""); printf "%s\n",[=14=];}' ... 将其格式化为单行并将其粘贴到 connection.json 中作为 root_cert

同样,我已将 cert.pem 文件复制到链代码容器中,并将环境变量 CORE_CHAINCODE_TLS_CLIENT_CACERT_FILE 设置为指向该文件。但是,对等点仍然无法连接到容器。

ClientHandshake -> ERRO 06c Client TLS handshake failed after 752.754µs with error: tls: first record does not look like a TLS handshake

更新 2:

好像我在链代码服务上设置了错误的环境变量。 CORE_CHAINCODE_TLS_CERT_FILE 必须设置为生成的 /signcerts/cert.pemCORE_CHAINCODE_TLS_KEY_FILE 必须设置为来自 /keystore.

的私钥

链码服务现在似乎可以接受证书,但对等点抱怨它们是由未知机构签署的。

更新 3:

又一点进步。好像我在 fabric-ca-client 命令中犯了一个错误。我不小心设置了 csr.cn 参数,从而覆盖了我的 CA 主机名。在他的帮助下,我能够在我的 CA 中注册我的链代码服务,并获得相应的 TLS 证书,以便对我的服务有效并通过组织 CA 结帐:-)

fabric-ca-client register --caname $CANAME --id.name $NAME --id.secret $PW --tls.certfiles $certfile --loglevel error
fabric-ca-client enroll -u https://$NAME:$PW@$CA_HOST_ADDRESS:$nodePort --caname $CANAME -M "$chainDir/msp" --csr.hosts chain-$validK8SHostName --tls.certfiles $certfile --loglevel error
fabric-ca-client enroll -u https://$NAME:$PW@$CA_HOST_ADDRESS:$nodePort --caname $CANAME -M "$chainDir/tls" --enrollment.profile tls --csr.hosts chain-$validK8SHostName --csr.hosts localhost --tls.certfiles $certfile --loglevel error

initializing a CA server 上的 Fabric CA 文档提到:

The fabric-ca-server init command generates a self-signed CA certificate unless the -u <parent-fabric-ca-server-URL> option is specified. If the -u is specified, the server’s CA certificate is signed by the parent Fabric CA server. In order to authenticate to the parent Fabric CA server, the URL must be of the form <scheme>://<enrollmentID>:<secret>@<host>:<port>, where <enrollmentID> and <secret> correspond to an identity with an hf.IntermediateCA attribute whose value equals true.

它还说你可以设置一个已经生成的密钥和证书文件

If you want the Fabric CA server to use a CA signing certificate and key file which you provide, you must place your files in the location referenced by ca.certfile and ca.keyfile respectively. Both files must be PEM-encoded and must not be encrypted. More specifically, the contents of the CA certificate file must begin with -----BEGIN CERTIFICATE----- and the contents of the key file must begin with -----BEGIN PRIVATE KEY----- and not -----BEGIN ENCRYPTED PRIVATE KEY-----.

因此,如果您已经拥有 CA 服务器 运行,则应该可以获得由其签名的证书或创建一个并将其包含在您的子 CA 中

我终于找到了问题的答案。正如我在第三次更新中所述,我已经使用 fabric-ca-client 为我的链代码服务注册了一个身份。

fabric-ca-client register --caname $CANAME --id.name $NAME --id.secret $PW --tls.certfiles $certfile --loglevel error
fabric-ca-client enroll -u https://$NAME:$PW@$CA_HOST_ADDRESS:$nodePort --caname $CANAME -M "$chainDir/msp" --csr.hosts chain-$validK8SHostName --tls.certfiles $certfile --loglevel error
fabric-ca-client enroll -u https://$NAME:$PW@$CA_HOST_ADDRESS:$nodePort --caname $CANAME -M "$chainDir/tls" --enrollment.profile tls --csr.hosts chain-$validK8SHostName --csr.hosts localhost --tls.certfiles $certfile --loglevel error

请注意,validK8SHostName 只是我容器的主机名,其中的点被破折号代替(k8s 不允许在服务或容器名称中使用点)。

这些命令在我的 chaindDir 中生成了一个 msptls 文件夹。引用为 JSON 属性的 certificates/keys 使用 awk 'NF {sub(/\r/, ""); printf "%s\n",[=16=];}' 转换为单行。链代码容器的环境变量是实际文件(我已将它们作为秘密安装在我的 k8s 集群中)。

  • tls/signcerts -> “root_cert”属性 和 CORE_CHAINCODE_TLS_CERT_FILE 环境需要认证。
  • tls/keystore -> 为 CORE_CHAINCODE_TLS_KEY_FILE 环境设置的私钥。
  • tls/tlscacerts -> CORE_CHAINCODE_TLS_CLIENT_CA_CERT_FILE 环境需要证书。
  • msp/signcert -> "client_cert" 属性.
  • 需要证书
  • msp/keystore -> 为“client_key”设置的私钥 属性

通过设置,我可以启动以 TLS 终止的链代码容器,并且只与那些具有相应证书和私钥组合的对等方通信。因此,所有证书和密钥均由我的组织 CA 生成。

有关其他信息,https://github.com/hyperledgendary/contract-as-a-service 是一个将链代码显示为外部服务的示例存储库。

那里采用的方法确实是 Victor 上面描述的方法,据我所知这是一个很好的方法。