nodejs - error self signed certificate in certificate chain - javascript

I am facing a problem with client side https requests.
A snippet can look like this:
var fs = require('fs');
var https = require('https');
var options = {
hostname: 'someHostName.com',
port: 443,
path: '/path',
method: 'GET',
key: fs.readFileSync('key.key'),
cert: fs.readFileSync('certificate.crt')
}
var requestGet = https.request(options, function(res){
console.log('resObj', res);
}
What I get is Error: self signed certificate in certificate chain.
When I use Postman I can import the client certificate and key and use it without any problem. Is there any solution available?? I would also like to be given some lights on how postman handles the certificates and works.

Option 1: Disable the warning (useful for dev)
From your question I'm guessing you are doing this in development as you are using a self signed certificate for SSL communication.
If that's the case, add as an environment variable wherever you are running node
export NODE_TLS_REJECT_UNAUTHORIZED='0'
node app.js
or running node directly with
NODE_TLS_REJECT_UNAUTHORIZED='0' node app.js
This instructs Node to allow untrusted certificates (untrusted = not verified by a certificate authority)
If you don't want to set an environment variable or need to do this for multiple applications npm has a strict-ssl config you set to false
npm config set strict-ssl=false
Option 2: Load in CA cert, like postman (useful for testing with TLS)
If you have a CA cert already like the poster #kDoyle mentioned then you can configure in each request (thanks #nic ferrier).
let opts = {
method: 'GET',
hostname: "localhost",
port: listener.address().port,
path: '/',
ca: fs.readFileSync("cacert.pem")
};
https.request(opts, (response) => { }).end();
Option 3: Use a proper SSL Cert from a trusted source (useful for production)
letsencrypt.org is free, easy to set up and the keys can be automatically rotated. https://letsencrypt.org/docs/

You can fix this issue using NODE_TLS_REJECT_UNAUTHORIZED=0 in the terminal or inserting the following line within the JS file.
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;
Beware that this a hack and it should not be used in production.
If you are using windows then run the following command in the command prompt:
set NODE_TLS_REJECT_UNAUTHORIZED=0
After that, npm install <my-package> will work.

for Nodemailer:
adding
tls: {
rejectUnauthorized: false
}
solved my problem.
Overall code looks liek this:
nodemailer.createTransport({
host: process.env.MAIL_SERVER,
secure: false,
port: 587,
auth: {
user: process.env.MAIL_USERNAME,
pass: process.env.MAIL_PASSWORD
},
tls: {
rejectUnauthorized: false
}
}

You can write command npm config set strict-ssl false

you just add at the start of your code this line:
process.env.NODE_TLS_REJECT_UNAUTHORIZED='0'
And everything solved, but in any case it is not recommendable, I am investigating the solution of https://letsencrypt.org/

Turning off verification is quite a dangerous thing to do. Much better to verify the certificate.
You can pull the Certificate Authority certificate into the request with the ca key of the options object, like this:
let opts = {
method: 'GET',
hostname: "localhost",
port: listener.address().port,
path: '/',
ca: await fs.promises.readFile("cacert.pem")
};
https.request(opts, (response) => { }).end();
I put a whole demo together of this so you can see how to construct SSL tests.
It's here.

Do:
Better use this if running a node script for standalone purpose,
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;
Don't:
instead of changing all default request process.
npm config set strict-ssl=false
i.e., don't alter your node config, else it will apply to all your requests, by making it default config. So just use it where necessary.

The node application needs to have the CA certificate added to the existing CA (Mozilla) certificates.
We start node using a service, and add the environment variable, NODE_EXTRA_CA_CERTS
[Service]
Restart=always
User=<...>
Group=<...>
Environment=PATH=/usr/bin:/usr/local/bin
Environment=NODE_ENV=production
Environment=NODE_EXTRA_CA_CERTS=/<...>/.ssl/extra_certs.pem
WorkingDirectory=/<...>
ExecStart=/usr/bin/node -r dotenv/config /<.....>/server.js dotenv_config_path=/<....>/.env
This way we can use the same application to call services using popular CAs or our own self signed certs, and we don't have to turn off SSL checking.
In linux there is an easy way to get the certificate, use this post: Use self signed certificate with cURL?
You create your certificate using:
$ echo quit | openssl s_client -showcerts -servername server -connect server:443 > cacert.pem
then copy that .pem file as the extra_cert.pem. You can only have one pem file, but you can append multiple pem files into one file.
I hope this helps someone, it took me a while to find the different parts to make this work.

For what it's worth, after spending a day and a half trying to track this one down it turned out the error was caused by a setting on my company's firewall that IT had to disable. Nothing anywhere on the internet did anything to fix this.

process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0; Even though its not worked ...
Not Able to Install Cypress:
S C:\Cypress> export NODE_TLS_REJECT_UNAUTHORIZED='0' node app.js
export : The term 'export' is not recognized as the name of a cmdlet, function, script
file, or operable program. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.
At line:1 char:1
export NODE_TLS_REJECT_UNAUTHORIZED='0' node app.js
+ CategoryInfo : ObjectNotFound: (export:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

Related

process.env doesn't contain ENV VARS when `npm run build` (Ubuntu)

I'm deploying VueJS project. There is a file that contain API URLs where I use process.env. If API_URL is defined in production only so I can use localhost on my development server and API_URL in the production.
const apiRoot = process.env.API_URL || 'http://127.0.0.1:8000'
export default {
root: apiRoot,
auth: {
jwt: {
create: urljoin(apiRoot, "auth/jwt/login/"),
refresh: urljoin(apiRoot, "auth/jwt/refresh/"),
},
loginPage: "/login",
me: urljoin(apiRoot,"users/me/")
}
}
On the server, I've added EXPORT API_URL='my.api.url' and then I ran npm run build. Then I realized it is still using 127.0.0.1:8000 so I also added the ENV VAR to /etc/environment file.
Again, no success. I've rebooted the server.
In cmd line I can do this:
echo $API_URL
'my.api.url'
How to make it work? Or how to debug this issue?
The solution is simple. Each ENV VAR must start with VUE_APP_.
So instead of setting API_URL
I need to set VUE_APP_API_URL

next.js environment variables are undefined (Next.js 10.0.5)

I am coding a website with Next.js and I tried to add google Tag Manager.
I followed the tutorial on the Next.js Github example but for some reasons I can't access to my environment variables.
It says my variable is undefined.
I created a file .env.local on my project folder (at the same level as components, node_modules, pages, etc)
In this file I created a variable like this (test purpose) :
NEXT_PUBLIC_DB_HOST=localhost
And on my index page I tried this code :
console.log("test ", process.env.NEXT_PUBLIC_DB_HOST);
But in my console I get a "test undefined".
I tried to put my variable into an .env file instead, without success.
What I am doing wrong ?
This envs just works in Server Side. To access this envs in Client Side, you need declare in the next.config.js
This way:
module.exports = {
reactStrictMode: true,
env: {
BASE_URL: process.env.BASE_URL,
}
}
Create .env (all environments), .env.development (development environment), and .env.production (production environment).
Add the prefix NEXT_PUBLIC to all of your environment variables.
NEXT_PUBLIC_API_URL=http://localhost:3000/
Use with prefix process.env
process.env.NEXT_PUBLIC_API_URL
Stop the server and restart it:
npm run dev
I hope it works.
This solution for latest version of nextJs (above 9)
Restarting the server worked for me.
Edit & save .env.local
Stop the server and restart it, npm run dev
You should get an output on the next line like this:
> klout#0.1.0 dev
> next dev
Loaded env from [path]/.env.local
For those using NextJS +9 and looking for environment variables in the browser, you should use the NEXT_PUBLIC_ prefix. Example:
NEXT_PUBLIC_ANALYTICS_ID=123456789
See documentation for reference.
After spending countless hours on this, I found that there is a tiny little paragraph in both the pre and post nextjs 9.4 documentation:
(Pre-9.4) https://nextjs.org/docs/api-reference/next.config.js/environment-variables (same as this answer)
Next.js will replace process.env.customKey with 'my-value' at build time.
(^9.4) https://nextjs.org/docs/basic-features/environment-variables
In order to keep server-only secrets safe, Next.js replaces process.env.* with the correct values at build time.
Key words being BUILD TIME. This means you must have set these variables when running next build and not (just) at next start to be available for the client side to access these variables.
This is my next.config.js file.
/** #type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
env: {
BASE_URL: process.env.NEXT_PUBLIC_SITE_URL,
},
};
module.exports = nextConfig;
Restart the server and it worked fine. using Nextjs 12.1.0 with typescript
In my case, Im pasting REACT_APP_API_URL instead of NEXT_PUBLIC_API_URL.
Adding with the most recent version of the documentation on this, v12+.
Using the next.config.js file you can specify server and client variables:
module.exports = {
serverRuntimeConfig: {
// Will only be available on the server side
mySecret: 'secret',
secondSecret: process.env.SECOND_SECRET, // Pass through env variables
},
publicRuntimeConfig: {
// Will be available on both server and client
staticFolder: '/static',
},
}
You can still use an env.local file, and pass the variable in to the next.config.js file. For example:
publicRuntimeConfig: {
DB_URL: process.env.DB_URL
}
And then you can access the variable like this:
import getConfig from 'next/config';
const { publicRuntimeConfig } = getConfig();
publicRuntimeConfig.DB_URL;

How to send trace data to Jaeger through OpenTelemetry in front end app?

Background
I am trying to trace in a front end app.
I am not be able to use #opentelemetry/exporter-jaeger since I believe it is for Node.js back end app only.
So I am trying to use #opentelemetry/exporter-collector.
1. Succeed to print in browser console
First I tried to print the trace data in the browser console. And
the code below succeed printing the trace data.
import { CollectorTraceExporter } from '#opentelemetry/exporter-collector';
import { DocumentLoad } from '#opentelemetry/plugin-document-load';
import { SimpleSpanProcessor, ConsoleSpanExporter } from '#opentelemetry/tracing';
import { WebTracerProvider } from '#opentelemetry/web';
const provider = new WebTracerProvider({ plugins: [new DocumentLoad()] });
provider.addSpanProcessor(new SimpleSpanProcessor(new ConsoleSpanExporter()));
provider.register();
2. Failed to forward to Jaeger
Now I want to forward them to Jaeger.
I am running Jaeger all-in-one by
docker run -d --name jaeger \
-e COLLECTOR_ZIPKIN_HTTP_PORT=9411 \
-p 5775:5775/udp \
-p 6831:6831/udp \
-p 6832:6832/udp \
-p 5778:5778 \
-p 16686:16686 \
-p 14268:14268 \
-p 9411:9411 \
jaegertracing/all-in-one:1.18
Based on the Jaeger port document, I might be able to use these two ports (if other ports work, that will be great too!):
14250 HTTP collector accept model.proto
9411 HTTP collector Zipkin compatible endpoint (optional)
Then I further found more info about this port:
Zipkin Formats (stable)
Jaeger Collector can also accept spans in several Zipkin data format,
namely JSON v1/v2 and Thrift. The Collector needs to be configured to
enable Zipkin HTTP server, e.g. on port 9411 used by Zipkin
collectors. The server enables two endpoints that expect POST
requests:
/api/v1/spans for submitting spans in Zipkin JSON v1 or Zipkin Thrift format.
/api/v2/spans for submitting spans in Zipkin JSON v2.
I updated my codes to
import { CollectorTraceExporter, CollectorProtocolNode } from '#opentelemetry/exporter-collector';
import { DocumentLoad } from '#opentelemetry/plugin-document-load';
import { SimpleSpanProcessor } from '#opentelemetry/tracing';
import { WebTracerProvider } from '#opentelemetry/web';
const provider = new WebTracerProvider({ plugins: [new DocumentLoad()] });
// The config below currently has issue
const exporter = new CollectorTraceExporter({
serviceName: 'my-service',
protocolNode: CollectorProtocolNode.HTTP_JSON,
url: 'http://localhost:9411/api/v1/spans', // Also tried v2
});
provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
provider.register();
However, I got bad request for both v1 and v2 endpoints without any response body returned
POST http://localhost:9411/api/v1/spans 400 (Bad Request)
POST http://localhost:9411/api/v2/spans 400 (Bad Request)
Any idea how can I make the request format correct? Thanks
UPDATE (8/19/2020)
I think Andrew is right that I should use OpenTelemetry collector. I also got some help from Valentin Marchaud and Deniz Gurkaynak
at Gitter. Just add the link here for further people who meet same issue:
https://gitter.im/open-telemetry/opentelemetry-node?at=5f3aa9481226fc21335ce61a
My final working solution posted at https://stackoverflow.com/a/63489195/2000548
Thing is, you should use opentelemetry collector if you use opentelemetry exporter.
Pls see schema in attachment
Also I created a gist, which will help you to setup
pls see
https://gist.github.com/AndrewGrachov/11a18bc7268e43f1a36960d630a0838f
(just tune the values, export to jaeger-all-in-one instead of separate + cassandra, etc)

Missing credentials for "PLAIN" error when using env variabele for password

I am trying to setup nodemail, but run into a strange issue where I cannot wrap my head around. Whenever I fill in the credentials as a string, everything works fine (but of course I don't want this). If I start using env variables, then I get the following error message:
UnhandledPromiseRejectionWarning: Error: Missing credentials for "PLAIN"
It's using a gmail account to send an email. The account has the bypass for unsafe accounts enabled. When I add a console.log() statement, the password is clearly visible. Does anyone have any idea why this is happening and how this can be resolved. Below you'll find a code snippet which sends the email.
import nodemailer from 'nodemailer';
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'some-account#gmail.com',
pass: process.env.PWD,
},
});
export const sendUserCreateEmail = (to, firstName) => {
const mailOptions = {
from: 'someone',
to: to,
subject: 'It works',
html: `
<p>It works!</p>
`,
};
return transporter.sendMail(mailOptions);
};
You need to install dotenv
npm install dotenv
then import it at your file
const dotenv = require('dotenv');
dotenv.config();
then it should works
I figured it out, although it is more of a work around. Apparently, the variables which where set by a dotenv file are not working there. I modified my npm command to include the variables and then it works as expected.
PWD=password node index.js
I can set these without committing them locally, so I can live with this solution for the moment. Still not sure why the dotenv variables are not accepted though.

Meteor-Up (mup) error after "mup init"

I am trying to use mup to deploy a meteor app to my DigitalOcean droplet.
What I have done so far
Followed instructions on "Meteor-Up" website http://meteor-up.com/getting-started.html.
Installed mup via "npm install --global mup"
Created ".deploy" folder in my app directory. Ran "mup init".
Configured file "mup.js" file for my app, ran "mup setup".
Here is where I ran into an error. Upon running "mup setup", I am hit with the following error. [
What I tried:
I suspected that there could have been an issue with my syntax when configuring the mup.js file. After double-checking and not finding any error, I decided to re-install mup, and try running "mup setup" without modifying the "mup.js" file. However, I still receive the same error message.
Furthermore, after running "mup init", I can no longer run "mup" either, as I receive the same error as seen above. I suspect therefore that the issue is with the mup.js file. I have attached the generic version provided by meteor-up below (which still causes the error seen above).
module.exports = {
servers: {
one: {
// TODO: set host address, username, and authentication method
host: '1.2.3.4',
username: 'root',
// pem: './path/to/pem'
// password: 'server-password'
// or neither for authenticate from ssh-agent
}
},
app: {
// TODO: change app name and path
name: 'app',
path: '../app',
servers: {
one: {},
},
buildOptions: {
serverOnly: true,
},
env: {
// TODO: Change to your app's url
// If you are using ssl, it needs to start with https://
ROOT_URL: 'http://app.com',
MONGO_URL: 'mongodb://localhost/meteor',
},
// ssl: { // (optional)
// // Enables let's encrypt (optional)
// autogenerate: {
// email: 'email.address#domain.com',
// // comma separated list of domains
// domains: 'website.com,www.website.com'
// }
// },
docker: {
// change to 'abernix/meteord:base' if your app is using Meteor 1.4 - 1.5
image: 'abernix/meteord:node-8.4.0-base',
},
// Show progress bar while uploading bundle to server
// You might need to disable it on CI servers
enableUploadProgressBar: true
},
mongo: {
version: '3.4.1',
servers: {
one: {}
}
}
};
Any help would be greatly appreciated!
Thank you
The error dialog you posted shows a syntax error at line 10, character 5.
If you take a look:
module.exports = {
servers: {
one: {
// TODO: set host address, username, and authentication method
host: '1.2.3.4',
username: 'root',
// pem: './path/to/pem'
// password: 'server-password'
// or neither for authenticate from ssh-agent
}
^^^ This character
},
It's a closing brace which JS was not expecting. So why was it unexpected, lets move back to the last valid syntax:
module.exports = {
servers: {
one: {
// TODO: set host address, username, and authentication method
host: '1.2.3.4',
username: 'root',
^^^ This character
// pem: './path/to/pem'
// password: 'server-password'
// or neither for authenticate from ssh-agent
}
},
Well, looks like a comma which isn't followed by another key-value pair. Also known as a syntax error.
Take the comma out and things should be fine again!
I faced this same issue today. The problem is that Windows is trying to execute the mup.js file as a JScript script.
Here is the solution from the Meteor Up Common Problems page:
Mup silently fails, mup.js file opens instead, or you get a Windows script error
If you are using Windows, make sure you run commands with mup.cmd instead of mup , or use PowerShell.
That is, instead of mup setup, run mup.cmd setup.

Categories