dotnet / aspire

Tools, templates, and packages to accelerate building observable, production-ready apps
https://learn.microsoft.com/dotnet/aspire
MIT License
3.83k stars 457 forks source link

Node.js app resources added with AddNpmApp/AddNodeApp fail to fetch content from ASP.NET Core apps over HTTPS #3324

Open DamianEdwards opened 7 months ago

DamianEdwards commented 7 months ago

The AspireWithNode sample is failing after updating to preview.5 due to Node.js' internal fetch() stack rejecting self-signed certificates by default, even if they're trusted by the host (in this case Windows). I believe this is because Node.js statically links OpenSSL rather than call through the host's crypto stack.

Some options to workaround (from Bing Chat) follow. If we wanted to apply one of these automatically in development when AddNpmApp or AddNodeApp is called, the most specific option appears to be exporting the ASP.NET Core HTTPS dev cert (public key only) and then setting the NODE_EXTRA_CA_CERTS environment variable on the Node.js app:

When working with Node.js and making HTTP requests using the Fetch API, you might encounter issues related to self-signed certificates. Self-signed certificates are often used for testing purposes or in private intranet services. Here are some approaches to handle self-signed certificates in Node.js:

  1. Ignoring SSL Verification (Not Recommended):

    • You can disable SSL verification altogether by setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to 0. However, this approach is not recommended because it disables SSL verification for all requests, making your application vulnerable to security risks.
    • Example:
      process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
  2. Using a Custom Agent:

    • Create a custom HTTPS agent with the rejectUnauthorized option set to false. This approach allows you to selectively ignore SSL verification for specific requests while still validating other certificates.
    • Example:

      const fetch = require('node-fetch');
      const https = require('https');
      
      const httpsAgent = new https.Agent({ rejectUnauthorized: false });
      
      const response = await fetch(url, {
          method: 'POST',
          headers: headers,
          body: body,
          agent: httpsAgent,
      });
  3. Monkey Patching the tls Module:

    • You can monkey-patch the tls module to support self-signed certificates with custom root certificate authorities (CAs). This approach allows you to append extra root CAs to the default list.
    • Example:
      const tls = require('tls');
      const secureContext = tls.createSecureContext();
      secureContext.context.addCACert(`-----BEGIN CERTIFICATE-----\n...`);
  4. Using Environment Variables:

    • Set the NODE_EXTRA_CA_CERTS environment variable to the path of a file containing additional root certificates in PEM format. Node.js will add these certificates to its list of hardcoded certificates.
    • Example:
      NODE_EXTRA_CA_CERTS=./rootCA.crt node server.js

If you're testing locally or in a controlled environment, proceed with caution and choose the most appropriate method based on your use case. 🛡️🔒

Source: Conversation with Bing, 4/1/2024 (1) how can I force fetch to accept a self-signed certificate in a web app .... https://stackoverflow.com/questions/67117016/how-can-i-force-fetch-to-accept-a-self-signed-certificate-in-a-web-app-front-end. (2) Monkey patching tls in node.js to support self-signed certificates with .... https://medium.com/trabe/monkey-patching-tls-in-node-js-to-support-self-signed-certificates-with-custom-root-cas-25c7[3](https://stackoverflow.com/questions/52478069/node-fetch-disable-ssl-verification)96dfd2a. (3) node.js - Node-fetch: Disable SSL verification - Stack Overflow. https://stackoverflow.com/questions/52[4](https://stackoverflow.com/questions/68896243/how-to-properly-configure-node-js-to-use-self-signed-root-certificates)78069/node-fetch-disable-ssl-verification. (4) How to properly configure node.js to use Self Signed root certificates?. https://stackoverflow.com/questions/68896243/how-to-properly-configure-node-js-to-use-self-signed-root-certificates. (5) Ignore invalid self-signed ssl certificate in node.js with https .... https://stackoverflow.com/questions/10888610/ignore-invalid-self-signed-ssl-certificate-in-node-js-with-https-request. (6) undefined. https://x.x.x.x:8000. (7) undefined. https://jsonplaceholder.typicode.com/todos/1. (8) Accept self-signed certificates for undici fetch - Stack Overflow. https://stackoverflow.com/questions/71946885/accept-self-signed-certificates-for-undici-fetch. (9) Fixing the Custom CA Problem in Node.js — Bossy Lobster. https://blog.bossylobster.com/2021/05/node-ca-append.html. (10) How to add custom certificate authority (CA) to nodejs. https://stackoverflow.com/questions/29283040/how-to-add-custom-certificate-authority-ca-to-nodejs. (11) GitHub - dhermes/ca-append-js: Monkey-patching Node.js tls Module .... https://github.com/dhermes/ca-append-js. (12) How to disable SSL verification in node.js - Stack Overflow. https://stackoverflow.com/questions/69596183/how-to-disable-ssl-verification-in-node-js. (13) How do you disable SSL verification in Fetch? - Technical-QA.com. https://technicqa.com/how-do-you-disable-ssl-verification-in-fetch/. (14) node.js - How can I ignore SSL/TLS validation using the Fetch API .... https://stackoverflow.com/questions/57117388/how-can-i-ignore-ssl-tls-validation-using-the-fetch-api. (15) How to Add an SSL Certificate to a Node.js Application - MUO. https://www.makeuseof.com/node-js-ssl-certificate-how-add/. (16) How to Add Self Signed SSL Certificate in Nodejs Server. https://thriveread.com/nodejs-server-self-signed-ssl-certificate/. (17) How do I use a self signed certificate for a HTTPS Node.js server?. https://stackoverflow.com/questions/19665863/how-do-i-use-a-self-signed-certificate-for-a-https-node-js-server. (18) Step-by-Step: Creating your own Self-Signed Certificate ... - Medium. https://medium.com/@ansont/step-by-step-creating-your-own-self-signed-certificate-authority-in-node-js-7500550a943a. (19) undefined. https://localhost:8888. (20) undefined. https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt. (21) undefined. https://external-login-api.com.

DamianEdwards commented 7 months ago

More detail on this, RE sending to the OTLP endpoint from a Node.js app over HTTPS, it seems the gRpc stack for Node.js doesn't support a flag to disable cert verification. Instead they recommend that the CA file for the self-signed cert blob is passed explicitly when initializing the channel credentials (see https://github.com/grpc/grpc-node/issues/160).

afscrome commented 6 months ago

In environments where your company deploys a TLS inspection appliance, users may already have many of these environment variables set. Aspire should make sure to add to the existing configuration, rather than overwrite it completely.