edgebitio / enclaver

Open source toolkit created to enable easy adoption of software enclaves
https://edgebit.io/enclaver
Apache License 2.0
123 stars 12 forks source link

Does Enclaver support mTLS / self-signed certificates? #184

Open mderriey opened 8 months ago

mderriey commented 8 months ago

Hi, it's me again 👋

I'm spiking running a production-grade Vault cluster in Enclaver.

I'm having issues joining a second node to a cluster, at the very last step where the existing leader node needs to communicate to the new-joining node with mTLS. The client certificate is self-signed and generated by Vault, see an excerpt from the official documentation:

[...] For the request forwarding method, the servers need direct communication with each other. In order to perform this securely, the active node also advertises, via the encrypted data store entry, a newly-generated private key (ECDSA-P521) and a newly-generated self-signed certificate designated for client and server authentication. Each standby uses the private key and certificate to open a mutually-authenticated TLS 1.2 connection to the active node via the advertised cluster address. When client requests come in, the requests are serialized, sent over this TLS-protected communication channel, and acted upon by the active node. The active node then returns a response to the standby, which sends the response back to the requesting client.

Unfortunately, this communication fails with the following error message from Vault:

{
  "@level": "error",
  "@message": "failed to heartbeat to",
  "@module": "storage.raft",
  "@timestamp": "2023-12-01T09:15:23.527220Z",
  "backoff time": 2500000000,
  "error": "dial tcp 10.1.54.175:8201: connect: network is unreachable",
  "peer": "10.1.54.175:8201"
}

Things I've confirmed:

Do you know if there's something in Enclaver that would prevent this from happening, or if maybe there's a way to make this work?

Thanks, please let me know if you need additional information.

mderriey commented 8 months ago

I don't know if that helps, but I tried running the target Docker image through several ways.

enclaver run \
  --debug-mode \
  --publish 8200:8200 \
  --publish 8201:8201 \
  vault:enclave
docker run \
  --rm -it \
  --detach \
  --cap-add=IPC_LOCK \
  --device=/dev/nitro_enclaves \
  --publish 8200:8200 \
  --publish 8201:8201 \
  --name=vault \
  vault:enclave

I also tried the docker command with --net=host and without the --publish arguments as per the guide on running Vault with Enclaver, but the outcome was the same.

crawford commented 8 months ago

Hey, welcome back! 👋

I'm pretty sure this isn't working because Enclaver only proxies HTTP egress traffic, while raft uses "raw" TCP. You'll need to use something like ncat to proxy the raft traffic over HTTP. So, within each enclave, you'll want to run vault and two instances of ncat - one which listens on 8201 and proxies the traffic over HTTP, and the second, which listens for HTTP-proxied traffic and forwards it to Vault.

eyakubovich commented 8 months ago

I think you can just run one instance of ncat to egress out of the encalve. For ingress, Enclaver works fine with TCP.

There's an issue (https://github.com/edgebitio/enclaver/issues/69) to support transparent TCP proxy so any TCP communication can work but it hasn't been implemented yet.

BTW, we're happy to answer question here but we also have Discord which works a bit better for more interactive discussions.