Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support NODE_EXTRA_CA_CERTS #11724

Closed
wants to merge 1 commit into from

Conversation

LudvigHz
Copy link
Contributor

@LudvigHz LudvigHz commented Jun 9, 2024

What does this PR do?

  • Code changes

Load ca certificates from NODE_EXTRA_CA_CERTS

Respects the Node.js API and loads the CA file pointed to by the environment variable NODE_EXTRA_CA_CERTS into the global SSL context.

This works for fetch, https.request and (should also cover) requests made by the bun CLI, f.ex bun install.

I haven't added tests for bun install since there isn't really existing test infra for bun install network activity.

How did you verify your code works?

I wrote automated tests

If Zig files changed:

  • I checked the lifetime of memory allocated to verify it's (1) freed and (2) only freed when it should be
  • I included a test for the new code, or an existing test covers it
  • JSValue used outside outside of the stack is either wrapped in a JSC.Strong or is JSValueProtect'ed
  • I wrote TypeScript/JavaScript tests and they pass locally (bun-debug test test-file-name.test)

A couple notes on this:

  • I looked into using the envLoader for getting the env var, but in (almost) all instances the HTTPThread is initialized before the envLoader, and it would require quite a bit of rebasing to get the envMap context into the HTTPContext initialization. The way it's done now, it requires minimal code changes while still being compatible with Node.js.
  • I passed the ca file into the socket context initialization, since the option is already there, however the code for loading ca files to the certificate store will crash when it fails (see the last test I added). I looked into exposing the API for adding additional CAs to the global socket context, so I could do that as well, if the current behavior is unwanted. I just went with the current method to minimize changes and keeping it simple.

Fixes #7124
Fixes #7200
Fixes #271

Respects the Node.js API and loads the CA file pointed to by the
environment variable NODE_EXTRA_CA_CERTS into the global SSL context.
Copy link
Contributor

github-actions bot commented Jun 9, 2024

@LudvigHz, your commit has failing tests :(

💪 1 failing tests Darwin AARCH64

  • test/js/node/http/node-http.test.ts SIGKILL

💻 1 failing tests Darwin x64 baseline

  • test/js/node/http/node-http.test.ts SIGKILL

💻 1 failing tests Darwin x64

  • test/js/node/http/node-http.test.ts SIGKILL

🐧💪 1 failing tests Linux AARCH64

  • test/js/node/http/node-http.test.ts SIGKILL

🐧🖥 2 failing tests Linux x64 baseline

  • test/js/node/http/node-http.test.ts SIGKILL
  • test/js/third_party/jsonwebtoken/noTimestamp.test.js 1 failing

🐧🖥 1 failing tests Linux x64

  • test/js/node/http/node-http.test.ts SIGKILL

🪟💻 2 failing tests Windows x64 baseline

  • test/integration/expo-app/expo.test.ts 1 failing
  • test/js/node/http/node-http.test.ts SIGKILL

🪟💻 1 failing tests Windows x64

  • test/js/node/http/node-http.test.ts SIGKILL

View logs

var extra_cas: ?std.ArrayList([*c]const u8) = null;

blk: {
if (std.process.getEnvVarOwned(default_allocator, "NODE_EXTRA_CA_CERTS")) |extra_ca_certs_path| {
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should use something in DotEnv.Loader and be cached there. We will need to add support for this in several places instead of only in the http client.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okey, that was the main thing I was unsure about. I initially looked at going that route, but it ended up being kind of complicated with the current architecture of how/when the HTTPThread is initialized.

But then I'll move this there instead and I will have to change the initialization of the HTTPThread to depend on DotEnv.Loader. I do agree it's also better option devex wise.

If you have any ideas on how to best get the ca file contents into the context of the https context initialization, I'd happily take some pointers as well 😅 (the first/only way I saw how to do this involved passing the dotenv context around alot)


blk: {
if (std.process.getEnvVarOwned(default_allocator, "NODE_EXTRA_CA_CERTS")) |extra_ca_certs_path| {
const file = bun.openFile(extra_ca_certs_path, .{ .mode = .read_only }) catch |err| {
Copy link
Collaborator

@Jarred-Sumner Jarred-Sumner Jun 9, 2024

Choose a reason for hiding this comment

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

There are way too many ways to read files in Bun's codebase which is very confusing (not your fault at all)

Instead of this, let's do:

const contents = bun.sys.File.readFromUserInput(std.fs.cwd(), extra_ca_certs_path, bun.default_allocator)

And not in here, instead in DotEnv.Loader

@@ -0,0 +1,17 @@
(async () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

IIFEs like this are unnecessary in Bun. Bun will use ESM by default.

const run = async (done, env, func: (proc: Subprocess<"pipe">) => Promise<void>) => {
const server = https.createServer(
{
key: nodefs.readFileSync(path.join(import.meta.dir, "fixtures", "openssl_localhost.key")),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Looks like these files were not committed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Whoops, I initially based this off of #11322. I'll rebase now that that's merged and we can reuse the same certs.

Choose a reason for hiding this comment

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

@LudvigHz
Is there any update for the status of this PR?
🙏

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 haven't had the time to work on it lately. And as I'll need to refactor alot of the http initialization it's going to require quite a bit more work than what this PR proposes currently.

But hopefully I'll have some free time soon to look at it some more :)

@Jarred-Sumner
Copy link
Collaborator

Closing due to inactivity, but feel free to send another if you get the time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants