Connect: Accommodate for making gRPC server creds in shared process#1220
Conversation
Some of the timeouts in preload.ts, the shared process and tshd are set to 10s. If the timeout to resolve the network address is lower or equal to that, those timeout won't have the chance kick in. Hence setting the timeout to a slightly larger value.
Without this, the cert generated by makeCert was failing when loaded
in Go as the gRPC server cert. The error message was:
x509: certificate relies on legacy Common Name field, use SANs instead
See:
* https://stackoverflow.com/a/31143907/742872
* Search for "subjectAltName" https://github.com/digitalbazaar/forge/blob/2bb97afb5058285ef09bcf1d04d6bd6b87cffd58/README.md
| // | ||
| // `Renderer` and `Tshd` file names are also used on the tshd side. | ||
| export enum GrpcCertName { | ||
| Client = 'client.crt', |
There was a problem hiding this comment.
Now that we're going to have both a gRPC client and a gRPC server in the renderer process, the name "client" stopped being sufficient. I refactored this so that it closer reflects what we want to achieve with gRPC certs – each process owns its own key pair, keeps the private key in memory and the public key is saved to the file.
| const runtimeSettings = getRuntimeSettings(); | ||
| initializeLogger(runtimeSettings); | ||
| initializeServer(runtimeSettings); | ||
|
|
There was a problem hiding this comment.
This was just moved from the bottom of the file to the top, before function declarations so that you can immediately see what's going to be executed when this file is loaded.
| { | ||
| name: 'subjectAltName', | ||
| altNames: [ | ||
| { | ||
| type: 2, // DNS type | ||
| value: commonName, | ||
| }, | ||
| ], | ||
| }, |
There was a problem hiding this comment.
To my surprise, Go didn't complain when a cert without this was used as a client cert, but it was a problem when I tried to use it as a server cert for the client credentials.
avatus
left a comment
There was a problem hiding this comment.
I like it and I'm excited for what it leads to. Also, side note: what a succinct and informative PR.
| } | ||
|
|
||
| const { certsDir } = runtimeSettings; | ||
| const [rendererKeyPair, tshdCert, sharedCert] = await Promise.all([ |
There was a problem hiding this comment.
What happens if any of these promises fail?
There was a problem hiding this comment.
createGrpcCredentials will throw, then after it getElectronGlobals will throw. getElectronGlobals gets exposed through contextBridge as window.electron:
webapps/packages/teleterm/src/preload.ts
Line 33 in be9639e
It's used in boot.tsx:
webapps/packages/teleterm/src/ui/boot.tsx
Lines 13 to 14 in be9639e
getElectronGlobals in boot.tsx calls window.electron underneath, so it will fail as well, triggering the catch branch:
webapps/packages/teleterm/src/ui/boot.tsx
Lines 28 to 30 in be9639e
This will show the error to the user in the actual browser window.
Co-authored-by: Michael <michael.myers@goteleport.com>
gzdunek
left a comment
There was a problem hiding this comment.
Well done @ravicious! I don't have any comments to the code, I have to try it out (I'll do it on Monday).
|
I’m going to backport this once v11.0.0 is released. |
…1220) * Add comment to resolveNetworkAddress * Log errors during boot of React app * Connect: Accommodate for making gRPC server creds in shared process * Adjust timeout for resolveNetworkAddress Some of the timeouts in preload.ts, the shared process and tshd are set to 10s. If the timeout to resolve the network address is lower or equal to that, those timeout won't have the chance kick in. Hence setting the timeout to a slightly larger value. * makeCert: Add subjectAltName to certs Without this, the cert generated by makeCert was failing when loaded in Go as the gRPC server cert. The error message was: x509: certificate relies on legacy Common Name field, use SANs instead See: * https://stackoverflow.com/a/31143907/742872 * Search for "subjectAltName" https://github.com/digitalbazaar/forge/blob/2bb97afb5058285ef09bcf1d04d6bd6b87cffd58/README.md * Fix lint issues * Reword comment Co-authored-by: Michael <michael.myers@goteleport.com> * Remove unused imports Co-authored-by: Michael <michael.myers@goteleport.com>
…cess (#1220) (#1302) * Add comment to resolveNetworkAddress * Log errors during boot of React app * Connect: Accommodate for making gRPC server creds in shared process * Adjust timeout for resolveNetworkAddress Some of the timeouts in preload.ts, the shared process and tshd are set to 10s. If the timeout to resolve the network address is lower or equal to that, those timeout won't have the chance kick in. Hence setting the timeout to a slightly larger value. * makeCert: Add subjectAltName to certs Without this, the cert generated by makeCert was failing when loaded in Go as the gRPC server cert. The error message was: x509: certificate relies on legacy Common Name field, use SANs instead See: * https://stackoverflow.com/a/31143907/742872 * Search for "subjectAltName" https://github.com/digitalbazaar/forge/blob/2bb97afb5058285ef09bcf1d04d6bd6b87cffd58/README.md * Fix lint issues * Reword comment Co-authored-by: Michael <michael.myers@goteleport.com> * Remove unused imports Co-authored-by: Michael <michael.myers@goteleport.com> Co-authored-by: Michael <michael.myers@goteleport.com>
Equivalent Teleport PR: gravitational/teleport#16782.
On Windows, we use gRPC over TCP with mTLS since Node.js doesn't support UDS on Windows. Each process creates its own keypair and saves the public key to a predetermined location.
Up until now, these were the client-server pairs we had to support:
For tshd-initiated communication, the tshd process will need to create a client that will connect to a gRPC server operated by the renderer process of the Electron app.
grpcCredentialsrefactorpackages/teleterm/src/services/grpcCredentialsused to look like this:Now it looks like this:
clientCredentials.tsandserverCredentials.tscontained logic that was specific to a concrete process (renderer for clientCredentials). I extracted generic functions from those files. The orchestration of credentials for each process happens now in that process' main file.Instead of having a catch-all
helpers.tsorutils.tsfile, I split the generic functions into functions that operate primarily on files (files.ts) and functions that work with credentials (credentials.ts). IMHO it's very important to do that – having autils.tsfile is almost always a bad choice as it signals that we didn't spend enough time thinking how the contents of that file fit into the general structure of the project.