Handle TLS between Peer and CouchDB#5506
Conversation
db27c61 to
5d7ea9c
Compare
|
@mffrench Please tell me, did you use AI to generate the changes? |
|
@pfi79 : I used AI and reviewed/tested by myself and team (so more human than AI still) ... but AI still very usefull for documenting I think... |
bc997eb to
006e60d
Compare
Signed-off-by: Mathilde Ffrench <mathilde.ffrench@fr.ibm.com>
006e60d to
083806d
Compare
Yes, I see that you have modified |
@pfi79 : well I'm not sure. It could be myself while I was reporting some changes... I didn't found that change in my initial PR in our own Fabric fork... Any other feedbacks which can help improve that PR to make it merged ? |
|
This is a reasonable requirement and the code updates look pretty good to me. Any chance one of the existing committers can help with review/approve and merge it? |
There was a problem hiding this comment.
From where, from which page, will the user have to go here?
So far, this documentation page is not linked anywhere.
There was a problem hiding this comment.
I don't know... Maybe should it be accessible the same way https://github.com/hyperledger/fabric/blob/main/docs/source/couchdb_tutorial.rst is accessed by the user maybe ? Note however I acceded that doc by browsing docs/source directory only. I didn't know each doc in there was linked to some main doc and I'll be interested to know where is that main doc.
There was a problem hiding this comment.
See. Documentation is generated from the docs folder. And by searching or clicking on links, you can get to every page. The search is OK, let's leave it. But clicking on the links is necessary.
In other words, there must be a transition from somewhere to the page you are creating. This means that you need to add a link to your page to an existing page.
Look around, there are many examples.
There was a problem hiding this comment.
Alternatively, you can add changes to the documentation to an existing page. Maybe shorten the text.
Sorry, I haven't read the gist of the documentation yet.
| # TLS configuration for CouchDB connection | ||
| tls: | ||
| # Enable TLS for CouchDB connection (default: false) | ||
| # When enabled, the peer will use HTTPS to connect to CouchDB | ||
| # Environment variable: CORE_LEDGER_STATE_COUCHDBCONFIG_TLS_ENABLED | ||
| enabled: false | ||
| # Path to CA certificate file for verifying the CouchDB server certificate | ||
| # If not provided, the system's default CA certificate pool will be used. | ||
| # Environment variable: CORE_LEDGER_STATE_COUCHDBCONFIG_TLS_CACERTFILE | ||
| caCertFile: | ||
| # Skip server certificate verification (default: false) | ||
| # WARNING: This is insecure and should only be used for testing purposes. | ||
| # Environment variable: CORE_LEDGER_STATE_COUCHDBCONFIG_TLS_SKIPVERIFY | ||
| skipVerify: false |
There was a problem hiding this comment.
The tls setting style already exists in the project (see core.yaml and orderer.yaml). Try to do it in the same style. If this is not possible, please explain why.
There was a problem hiding this comment.
I'm not sure I understand the setting style you're speaking about. Here we want to set client TLS only to the couchdb and not both client & server. Is it the caCertFile: you would like to change to something like:
# X.509 certificate used for TLS when making client connections.
# If not set, peer.tls.cert.file will be used instead
clientCert:
file:
?
There was a problem hiding this comment.
Or is it the skyVerify you would like to remove ? I would say that can be an interesting option for some setups and I would advocate to keep it.
tls.enabled looks already be reused from the 'tls style' ...
Back to my previous comment about the caCertFile: clientCert example is not equivalent here. This the client certificate of the TLS client, not the certificate of the CA trusting the couchdb TLS identity. Also, we dont need Couchdb Client TLS identity because CouchDB doesn't handle mTLS. So finally I would tend to keep it that way.
Can you be please a bit more explicit if you think there is a blocker on the current proposal ?
There was a problem hiding this comment.
Here are some examples. If you look closely, they are all made in the same style, both clients and servers. I would like your change to be similar to these.
Sorry, I don't really like variety.
example of a tls section in core.yaml
# TLS configuration for the operations endpoint
tls:
# TLS enabled
enabled: false
# path to PEM encoded server certificate for the operations server
# The paths in this section may be relative to FABRIC_CFG_PATH or an absolute path.
cert:
file:
# path to PEM encoded server key for the operations server
key:
file:
# most operations service endpoints require client authentication when TLS
# is enabled. clientAuthRequired requires client certificate authentication
# at the TLS layer to access all resources.
clientAuthRequired: false
# paths to PEM encoded ca certificates to trust for client authentication
clientRootCAs:
files: []
example of tls section in orderer.yaml
# TLS configuration for the admin endpoint
TLS:
# TLS enabled
Enabled: false
# Certificate is the location of the PEM encoded TLS certificate
Certificate:
# PrivateKey points to the location of the PEM-encoded key
PrivateKey:
# Most admin service endpoints require client authentication when TLS
# is enabled. ClientAuthRequired requires client certificate authentication
# at the TLS layer to access all resources.
#
# NOTE: When TLS is enabled, the admin endpoint requires mutual TLS. The
# orderer will panic on startup if this value is set to false.
ClientAuthRequired: true
# Paths to PEM encoded ca certificates to trust for client authentication
ClientRootCAs: []
tls example from osnadmin
if *caFile != "" {
osnURL = fmt.Sprintf("https://%s", *orderer)
var err error
caCertPool = x509.NewCertPool()
caFilePEM, err := os.ReadFile(*caFile)
if err != nil {
return "", 1, fmt.Errorf("reading orderer CA certificate: %s", err)
}
if !caCertPool.AppendCertsFromPEM(caFilePEM) {
return "", 1, errors.New("failed to add ca-file PEM to cert pool")
}
tlsClientCert, err = tls.LoadX509KeyPair(*clientCert, *clientKey)
if err != nil {
return "", 1, fmt.Errorf("loading client cert/key pair: %s", err)
}
There was a problem hiding this comment.
I did read these examples already but I'm personally not agree to add configuration complexity on a use case which is much more simpler than Peer and Order TLS setup which handle both server TLS setup and client mTLS setup. HLF Peer to CouchDB connection is about configuring a client on the Peer for a simple TLS connection to a CouchDB server (and with no mTLS as CouchDB doesn't handle it).
Again, here we are configuring an HTTPs client only and we are requiring only 2 mandatory param:
TLSEnabled: wether or not we activate TLS between CouchDB & Peer
TLSCACertFile: the CA cert file of the _CouchDB_ server to make work TLS handshake
The last one is to reduce complexity on dev environment in some scenario :
TLSSkipVerify: viper.GetBool("ledger.state.couchDBConfig.tls.skipVerify"),
I dont see reasonable rational to add extra params & complexity to follow some examples which do not match the use case.
While I understand you don't like variety, please understand I don't like adding useless complexity : please explain the rational to increase code change complexity in that use case.
There was a problem hiding this comment.
Fabric is a very complex system.
In my opinion, adding a new tls assignment method, unlike the previous methods, complicates the entire system.
And I think it's ugly, but monotonous.
| scheme := "http" | ||
| if config.TLSEnabled { | ||
| scheme = "https" | ||
| couchdbLogger.Info("TLS is enabled for CouchDB connection") |
There was a problem hiding this comment.
You have 6 places in the code where INFO level logging is used. Consider making them DEBUG
Add TLS Support for Peer-to-CouchDB Connections
Type of change
Description
This pull request adds native TLS support for connections between Hyperledger Fabric Peers and CouchDB state databases, addressing a critical security vulnerability where all peer-to-CouchDB communication was previously unencrypted.
Problem:
Currently, Fabric peers connect to CouchDB using unencrypted HTTP connections, exposing CouchDB authentication credentials (transmitted in plaintext via HTTP Basic Auth) and the complete blockchain world state data. While documentation recommends co-locating peers and CouchDB on the same VM, this is insufficient for modern cloud-native deployments, particularly in Kubernetes environments where network traffic can be monitored by cloud provider administrators or untrusted parties.
Solution:
This PR implements comprehensive TLS support with server certificate verification, configurable TLS settings, and TLS 1.3 minimum version enforcement. The implementation is backward compatible (TLS disabled by default) and includes proper error handling and security logging.
Key Changes:
CouchDBConfigstructure with TLS fields (TLSEnabled,TLSCACertFile,TLSSkipVerify)createCouchInstance()to support HTTPS scheme when TLS is enabledloadTLSConfig()function for TLS configuration and certificate loadingcouchInstance.url()method to return https:// when TLS is enabledConfiguration Example:
Security Impact:
Additional details
Testing:
Implementation Notes:
crypto/tlspackageMigration Path:
Existing deployments can migrate to TLS by:
Related issues
Addresses security vulnerability: Lack of TLS support for peer-to-CouchDB connections exposes sensitive ledger data in cloud/Kubernetes deployments.
Release Note
Added TLS support for peer-to-CouchDB connections to encrypt communication and protect sensitive ledger data. New configuration options allow peers to connect to CouchDB over HTTPS with server certificate verification. This feature is particularly important for cloud-native and Kubernetes deployments where network traffic may be accessible to untrusted parties. TLS is disabled by default for backward compatibility. See documentation for configuration details and migration guidance.