[GODRIVER-1753] Mongo go driver - giving key mismatch error while connecting with ssl enabled and encrypted key Created: 17/Sep/20 Updated: 27/Oct/23 Resolved: 16/Nov/20 |
|
| Status: | Closed |
| Project: | Go Driver |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | prakhar deep | Assignee: | Divjot Arora (Inactive) |
| Resolution: | Works as Designed | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Description |
|
I'm getting following error while trying to connect to mongodb server from golang application kubernetes pod. I'm using mongo-go-driver version 1.4.1 Key is RSA encrypted. ---- PFB application code to connect }} }} Please help me in resolving key mismatch error. |
| Comments |
| Comment by Divjot Arora (Inactive) [ 16/Nov/20 ] | ||
|
Given that the linked PR would be a breaking behavioral change for the driver and there is a workaround for this issue, we've elected to close this ticket for now. | ||
| Comment by Divjot Arora (Inactive) [ 29/Oct/20 ] | ||
|
Apologies for the delay in reviewing the PR. After looking more into the tls.X509KeyPair function, I don't think the proposed solution is correct. I wrote up some test cases at this repository. When specifying a file that has multiple certificates, it seems that the tls.X509KeyPair function only uses the first rather than testing all of them. I also verified this with the function's source code]. The function first iterates through all blocks in the certPEMBlock parameter and stores all blocks of type "CERTIFICATE". However, the x509.ParseCertificate call only uses cert.Certificate[0], which indicates that all certificate blocks after the first are thrown away. Given this, we can't accept the proposed change as it would be a backwards-breaking behavioral change for the driver. You should be able to work around this by using a certificate file that only has one certificate, which is the generally accepted use case, or by ensuring that the correct certificate is at the end of the file. Would these be sufficient workarounds for you? – Divjot | ||
| Comment by Divjot Arora (Inactive) [ 27/Oct/20 ] | ||
|
community PR: https://github.com/mongodb/mongo-go-driver/pull/521 | ||
| Comment by prakhar deep [ 19/Oct/20 ] | ||
|
Hi Divjot, I looked into client options code ( https://github.com/mongodb/mongo-go-driver/blob/master/mongo/options/clientoptions.go ) and found out in the method addClientCertFromBytes, only last certificate is getting propagated if multiple certs are present. ( https://github.com/mongodb/mongo-go-driver/blob/935fe3f869a9d46940f402873c97c19d19a8d41d/mongo/options/clientoptions.go#L884 ) This is causing the key mismatch issue in tls config. When multiple certificates are present, code loops through and retains/propagates only the last one, which later causes key mismatch error. I have added code to keep appending certs to certblock to care of above scenario. Post that I'm now able to successfully connect to db from application code. (https://github.com/mongodb/mongo-go-driver/pull/521 Added this PR - please let me know if changes are ok) | ||
| Comment by Divjot Arora (Inactive) [ 19/Oct/20 ] | ||
|
Thank you for opening the PR at https://github.com/mongodb/mongo-go-driver/pull/521. I'll take a look at the PR this week and leave a review. If this is actually a bug, we'll try to get it merged for the 1.4.3 release. – Divjot | ||
| Comment by prakhar deep [ 14/Oct/20 ] | ||
|
Hi Divjot, Sorry for delay. I have tried the code you provided in the link in last comment. I didn't get any error while using it and log printed success after creating TLS pair. | ||
| Comment by Divjot Arora (Inactive) [ 30/Sep/20 ] | ||
|
Thanks for trying that out. At this point, I think the next step is to reproduce this without involving the driver. I've written up a gist with some code to load a certificate and an encrypted private key and use them to create a TLS key pair at https://gist.github.com/divjotarora/09d783ba857bbeebfca16d140d8e6505. I've verified that this works with my cert and key. The x509.DecryptPEMBlock call fails if I provide the wrong password and the tls.X509KeyPair call fails if I provide a different key that doesn't match the certificate, as expected. Can you try this script against your cert/key pair? Hopefully it will help us figure out why we haven't been able to reproduce this issue. – Divjot | ||
| Comment by prakhar deep [ 29/Sep/20 ] | ||
|
Hi, I tried the above mentioned URI but still getting key mismatch error. PFB version of go-driver & golang Mongo-go-driver version: v1.4.1 Go lang version: 1.12 OS: Red Hat Enterprise Linux 7.4
| ||
| Comment by Divjot Arora (Inactive) [ 23/Sep/20 ] | ||
|
prakhar.deep12@gmail.com I haven't found anything useful yet, but I think we can get rid of some variables by shortening the URI. I think this URI would be the minimal required one to reproduce the issue:
where "combined.pem" would be the path to the file that contains both the certificate and key concatenated and "passphrase" would be the password required for decryption. I tried this with the example certificate at https://github.com/mongodb/mongo-go-driver/blob/ce6e7c713cd1b1f44e544b062d0cc0bb7c8a1954/mongo/options/testdata/certificate.pem. It passed as-is and failed if I changed the password to an incorrect one, as expected. Can you try using this URI to see if that still shows this error? Also, can you provide the driver version, Go language version, and operating system you're using? – Divjot | ||
| Comment by Divjot Arora (Inactive) [ 23/Sep/20 ] | ||
|
prakhar.deep12@gmail.com I tried using the individual cert/key options with this URI:
and did not get any errors from the mongo.NewClient function. In your previous comment, you mentioned that you used the "tlsCertificateFile" and "tlsPrivateKey" options. I believe you need to use "tlsPrivateKeyFile" instead of "tlsPrivateKey" as documented in bullet (2) of https://godoc.org/go.mongodb.org/mongo-driver/mongo/options#ClientOptions.SetTLSConfig. Note that I don't think using the separate cert/key options will help as the code to read the cert/key and decrypt the key using the password is shared in both code paths. I also verified that we have at least one test case for an encrypted private key that requires a passphrase, so it's very strange to me that you're seeing this error. I will continue to investigate. | ||
| Comment by Divjot Arora (Inactive) [ 23/Sep/20 ] | ||
|
I'm not sure of the underlying problem yet, but using "sslCertificateFile" and "sslPrivateKeyFile" is not correct. We don't check for those URI options, so I believe what's happening there is that the parsing succeeds because those options are actually ignored. At that point, TLS is not properly configured, so all connections to the server fail. That would cause the "server selection error" on the first operation because we're not able to discover the servers. I will investigate why you're seeing parsing errors when using "tlsCertificateFile" and "tlsPrivateKey". I believe we have test cases for those combinations, so it's strange that you're seeing that error. | ||
| Comment by prakhar deep [ 23/Sep/20 ] | ||
|
I tried giving "tlsCertificateFile" and "tlsPrivateKey" in URI but it returned following error: "the tlsPrivateKeyFile URI option must be provided if the tlsCertificateFile option is specified" even though both options were provided. After going through code https://github.com/mongodb/mongo-go-driver/blob/master/x/mongo/driver/connstring/connstring.go looks like above error is occurring due to incorrect parsing. Same is the reason why earlier error was happening even though both private & public keys were matching. Finally, used "sslCertificateFile" and "sslPrivateKeyFile" option in URI and it worked. ( Both of these option variable are not mentioned in docs https://godoc.org/go.mongodb.org/mongo-driver/mongo/options#ClientOptions ). Also, I tried "sslClientCertificateKeyFile" earlier but was getting same key mismatch error. Now, I'm able to connect to client(mongo.Connect) but when trying to ping database receiving following error: "server selection error - incomplete read of message header: EOF "
| ||
| Comment by prakhar deep [ 23/Sep/20 ] | ||
|
Hi Divjot, I separated the key & cert to two different files and ran the above mentioned openssl commands. Output for both key and cert matched. (Also, just to add key.pem is encrypted and need a passphrase. ) Regards | ||
| Comment by Divjot Arora (Inactive) [ 22/Sep/20 ] | ||
|
Thanks for the information. I believe the error is coming from https://github.com/golang/go/blob/d42b32e321fa5c5d2c93b2ad22d48e804c9f45d2/src/crypto/tls/tls.go#L342. The driver users Go's tls.X509KeyPair function to create a tls.Certificate instance, which is then used to populate a tls.Config. That function is returning an error when comparing the public and private keys. The first step for debugging this is to make sure that the public and private keys match. Both of these parts are currently in the file specified by certFilePath. Can you move them into separate files like key.pem and cert.pem? After that, we can use the commands from https://support.comodo.com/index.php?/Knowledgebase/Article/View/684/17/how-do-i-verify-that-a-private-key-matches-a-certificate-openssl to verify them. You can run
and
If you'd prefer to verify this in a different way, https://stackoverflow.com/questions/274560/how-do-you-test-a-public-private-dsa-keypair also has some suggestions. Once you've done this verification, we can move forward with debugging this issue. – Divjot |