Skip to content

Conversation

@onelapahead
Copy link
Contributor

@onelapahead onelapahead commented Jul 14, 2021

Fixes

Originally p2p APIs were using req.client.getPeerCertificate().issuer to determine the ID of the DX which sent the request. This worked for self-signed certificates because the issuer == subject, however for CA-signed certs provisioned w/ cert-manger, or internal Kaleido certs signed with a environment's CA, the issuer != subject and it was causing issues with private messaging E2E tests in those environments. subject should be used because DX uses it to derive its own peer ID that it advertises on GET /id.

For example, w/ a cert-manager cert signed by a CA (the CA happened to not have an O or OU) the DX would get the following error when trying to hit another org's DX:

2021-07-14T16:54:18.679Z [ERROR]: post https://a-firefly-host/api/v1/messages attempt 0 [500] { error: 'Invalid peer' } utils.ts

By casting the socket of the req to the TLSSocket it allows Typescript to then retrieve the subject from the peer's certificate which is what should be used to derive the DX's ID from the O and OU.

Additions

With cert-manager certificates, the cert.pem does not include the CA which signed it. If the CA is self-signed, this needs to be advertised in GET /id so peers can include the CA in their HttpsAgent and when they persist the certs in the peer-certs directory.

This adds support to optionally (if the file exists) read a ca.pem file from the DATA_DIRECTORY (same directory as key.pem and cert.pem) and prepend it the cert.pem storing it in a new var certBundle. certBundle is then returned on GET /id so peers will receive both the cert and the provided CA. The cert var is left to only contain the cert.pem because including the CA seemed to break the server startup when used in the TLSContext.

While self-signed CAs were already supported by putting a ca.pem in the peer-certs directory before startup (as what was is currently documented in the README) this allows peers to have certs signed by separate CAs w/o every peer needing to be aware of them on startup. It also allows new DX peers to join the network with renewed CA certs.

Original Issue

These changes arose from issues we found w/ FF DX deployments using self-signed CAs where the NodeJS HTTPS agent couldn't trust the cert from a peer bc the CA wasn't included in the chain (in a lot of ways this was just a config issue):

2021-07-14T15:23:19.854Z [ERROR]: post https://a-firefly-host/api/v1/messages attempt 2 [undefined] Error: unable to verify the first certificate
    at TLSSocket.onConnectSecure (_tls_wrap.js:1514:34)
    at TLSSocket.emit (events.js:375:28)
    at TLSSocket._finishInit (_tls_wrap.js:936:8)
    at TLSWrap.ssl.onhandshakedone

However, in Kubernetes environments where peer-certs is backed by a PVC, the ca.pem cannot be included into the directory before startup without init/bootstrap scripts (for example see the Helm chart PR in firefly). Upon adding the ca.pem / certBundle feature the bug above around the subject of the peer certificate was then discovered and needed to be fixed.

Signed-off-by: hfuss <haydenfuss@gmail.com>
Signed-off-by: hfuss <haydenfuss@gmail.com>
@onelapahead onelapahead changed the title First Pass at Supporting Self-Signed CAs Enhancements to CA Support for mTLS Jul 15, 2021
@onelapahead onelapahead marked this pull request as ready for review July 15, 2021 01:05
@onelapahead onelapahead changed the title Enhancements to CA Support for mTLS Bug Fix and Other Enhancements to CA Support for mTLS Jul 15, 2021

export const extractPeerSenderFromRequest = (req: Request): string => {
const cert = ((req.socket) as TLSSocket).getPeerCertificate();
return getPeerID(cert.subject.O, cert.subject.OU);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may need to update custom.d.ts to avoid potential compiler issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hadn't hit compiler issues when I built and tested this code in my deployments, but I updated custom.d.ts for good measure and removed the unused interfaces.

certBundle = cert;
log.debug("Loaded cert");
}
log.debug("\n" + certBundle);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In an early prototype of DX the CA was explicitly loaded. However, later the code was simplified as the file can just be picked up when reading the cert files. The constant was left in the utils file. The key question would be, is there a reason why it is explicitly loaded here? I was under the impression that as long as the file is placed in the correct directory, it will be picked up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah so, if a ca.pem (or really so long as it is a .pem) is in the peer-certs that will definitely work like you said.

The biggest advantage of this is if a new org and DX comes along with a different / renewed CA cert. With this approach, the DX can advertise this CA as part of its cert so that the other existing DX's do not need to be redeployed in order to trust the new DX - essentially making CA-signed certs be treated / trusted more like self-signed certs (which is debatably not the best approach from a security perspective).

Copy link
Contributor Author

@onelapahead onelapahead Jul 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm alright with removing this for now to keep the change small and give us time to think this through more, but we will need DX to support org's having separate CAs for our FireFly deployments outside Kaleido (and ideally DX's do not need to be redeployed to have others' CAs as that causes a lot of discovery issues on the cloud engineering side).

…nt interface

Signed-off-by: hfuss <haydenfuss@gmail.com>
@gabriel-indik gabriel-indik merged commit b0adcdc into hyperledger:main Jul 15, 2021
@onelapahead onelapahead deleted the ca-cert-debugging3 branch July 15, 2021 17:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants