What is the difference between `process.env.USER` and `process.env.USERNAME` in Node? - node.js

This is the most robust documentation I can find for the process.env property: https://nodejs.org/api/process.html#process_process_env.
It mentions USER, but not USERNAME. On my machine (Windows/Bash), when I print the contents of process.env, I see USERNAME (my windows username) but not USER. Similarly, echo $USERNAME shows my name but echo $USER returns nothing.
What is the difference between USER and USERNAME? Is it an operating system thing? Are they interchangeable?

The documentation about process.env that you linked to shows an example environment; it is not meant to be normative. process.env can be basically anything -- its values generally have OS defaults provided by the shell, but ultimately they are controlled by the user and/or the process that launched your process.
ie, a user could run
$ USER=lies node script.js
...and process.env would not contain the real username.
If you're interested in getting information about the user your process is running as, call os.userInfo(), which is (mostly1) consistent across platforms.
> os.userInfo()
{ uid: -1,
gid: -1,
username: 'josh',
homedir: 'C:\\Users\\josh',
shell: null }
1 - on Windows, uid, gid, and shell are useless, as seen above
os.userInfo() calls uv_os_get_passwd, which returns the actual current effective user, regardless of what's in environment variables.
uv_os_get_passwd Gets a subset of the password file entry for the current effective uid (not the real uid). The populated data includes the username, euid, gid, shell, and home directory. On non-Windows systems, all data comes from getpwuid_r(3). On Windows, uid and gid are set to -1 and have no meaning, and shell is NULL.

process.env is the process's environment variables, which are supplied by the OS to the process.
This object can really contain just about anything, as specified the OS and the process that launches it, but by default Windows stores the username in USERNAME and Unix-like systems (Linux, macOS, etc.) store it in USER.

I was having a similar issue when trying to connect node.js to mysql via dotenv.
None of the many answers in the web did not resolve my issue.
This worked perfectly well, without the .env file, but only with the information required for authentication inserted into the app.js file. I have tried unsuccessfully any of the posted answers, which include (but not only):
changing the information inside the .env file to be with and without ""
changing the name of the .env file
changing the path of the .env file
describing the path to .env file
writing different variations of the dotenv commands inside app.js
At last, I have tried to find if I had installed the dotenv using the npm install dotenv command. Also I have tried to show the version of the dotenv from the console.log(dotenv.MY_ENV_VAR); which again, showed undefined.
The issue was related to the fact, that dotenv confused USER (of the system, again like you I was using Linux) with USERNAME (of the mysql database). Actually USER returns the current system user instead of the mysql database user, which I have set to USERNAME in the .env file for convenience. Now it was able to connect to the database!
To check this, you could use:
console.log(process.env.USER);
and:
console.log(process.env.USERNAME);
1st gives you the system user, whereas the 2nd gives the database user.
Actually, any name for the variable, that holds the username of the mysql database could be used, as far as it does not match the reserved name for the system username in Linux, which is USER.

Related

why does running `which` in a node child process result in different results?

when running the which command in terminal (for example, which yarn), I get a different result from when I'm running a node script (from the same location) which calls execSync('which yarn')
can someone explain why?
tldr;
// in terminal
which yarn
// results in
/Users/xxx/.nvm/versions/node/v17.1.0/bin/yarn
// in node
execSync('which yarn')
// results in
/var/folders/0j/xxx/T/yarn--xxx/yarn
It looks like the Node.js process is running as a different user (not as you), and that user has a different path from your account (or at least, it isn't running any .bashrc or similar specific to your user account that might add to the path). That makes sense given that your result refers to a folder specific to you (/Users/xxx/), but the one from Node.js refers to a central location shared by all users.

Safest way to store secret credentials on a production server [duplicate]

As you may see, I have my db connection file and another "protected" file, where my credentials are, and this file is included in .gitignore. I import it and reach the data. Quite basic. Therefore my questions are:
Is this the right way to do it?
If not, how should I do it? Plus: how could I add extra security to my account,connection?
Let's suppose I have a private collection, that no one should see, how could I protect specially this collection? I mean, with a password or a two step verification let's say.
Current code:
const mongoose = require("mongoose");
const mongoCredentials = require("../protected/mongoCredential");
const URI = `mongodb+srv://${mongoCredentials.username}:${mongoCredential.password}
#firstcluster-eldi8.mongodb.net/culturapp?retryWrites=true&w=majority`;
mongoose.connect(URI, { useUnifiedTopology: true, useNewUrlParser: true })
.then(db => console.log("MongoDB is connected"))
.catch(err => console.log(">> ERROR: ",err));
module.exports = mongoose;
...I have my db connection file and another "protected" file, where my credentials are, and this file is included in .gitignore. I import it and reach the data..
The correct way to do it is to use envrironmental variables.
Use environmental variables
Environmental variables are set on the environment, i.e your local development machine or the remote production server.
Then, within your app, you read the environment variables and use them appropriately.
There's (at least) a couple reasons it's usually done like this:
The credentials don't exist in a file that can be read by someone viewing the repository contents. Someone cloning the repository doesn't need to know your database credentials.
The credentials are likely different between environments. You are likely using a different database on your local development machine and a different database in your remote production server.
Here's how you set environment variables (this is for Linux, other OS's might be different):
$ export MONGO_DB_USERNAME=foo
$ export MONGO_DB_PASSWORD=bar
and here's how you read them within Node.js:
console.log(process.env.MONGO_DB_USERNAME) // logs 'foo'
console.log(process.env.MONGO_DB_PASSWORD) // logs 'bar'
or pass variables to the process when starting up
Alternatively, you can pass variables when starting up the process like so:
$ MONGO_DB_USERNAME=foo MONGO_DB_PASSWORD=bar node app.js
However that's generally discouraged since you're most probably starting your process through the npm start script. Since package.json, where the npm start command is defined, is always committed to the repository it defeats the whole purpose of hiding the credentials.
Like you mentioned along lines, using environment variables is more like security through obfuscation.
I would try to have the credentials in a separate configuration file. With a bit of design, encrypt this file and store those keys in secure enclaves or TPMs.
Check this thread.

How to authenticate without writing credentials in the actual code? [duplicate]

As you may see, I have my db connection file and another "protected" file, where my credentials are, and this file is included in .gitignore. I import it and reach the data. Quite basic. Therefore my questions are:
Is this the right way to do it?
If not, how should I do it? Plus: how could I add extra security to my account,connection?
Let's suppose I have a private collection, that no one should see, how could I protect specially this collection? I mean, with a password or a two step verification let's say.
Current code:
const mongoose = require("mongoose");
const mongoCredentials = require("../protected/mongoCredential");
const URI = `mongodb+srv://${mongoCredentials.username}:${mongoCredential.password}
#firstcluster-eldi8.mongodb.net/culturapp?retryWrites=true&w=majority`;
mongoose.connect(URI, { useUnifiedTopology: true, useNewUrlParser: true })
.then(db => console.log("MongoDB is connected"))
.catch(err => console.log(">> ERROR: ",err));
module.exports = mongoose;
...I have my db connection file and another "protected" file, where my credentials are, and this file is included in .gitignore. I import it and reach the data..
The correct way to do it is to use envrironmental variables.
Use environmental variables
Environmental variables are set on the environment, i.e your local development machine or the remote production server.
Then, within your app, you read the environment variables and use them appropriately.
There's (at least) a couple reasons it's usually done like this:
The credentials don't exist in a file that can be read by someone viewing the repository contents. Someone cloning the repository doesn't need to know your database credentials.
The credentials are likely different between environments. You are likely using a different database on your local development machine and a different database in your remote production server.
Here's how you set environment variables (this is for Linux, other OS's might be different):
$ export MONGO_DB_USERNAME=foo
$ export MONGO_DB_PASSWORD=bar
and here's how you read them within Node.js:
console.log(process.env.MONGO_DB_USERNAME) // logs 'foo'
console.log(process.env.MONGO_DB_PASSWORD) // logs 'bar'
or pass variables to the process when starting up
Alternatively, you can pass variables when starting up the process like so:
$ MONGO_DB_USERNAME=foo MONGO_DB_PASSWORD=bar node app.js
However that's generally discouraged since you're most probably starting your process through the npm start script. Since package.json, where the npm start command is defined, is always committed to the repository it defeats the whole purpose of hiding the credentials.
Like you mentioned along lines, using environment variables is more like security through obfuscation.
I would try to have the credentials in a separate configuration file. With a bit of design, encrypt this file and store those keys in secure enclaves or TPMs.
Check this thread.

Setting up environment variables in node, specifically, GOOGLE_APPLICATION_CREDENTIALS

I have a node application and I'm trying to use the google language api. I want to set the environment variable GOOGLE_APPLICATION_CREDENTIALS to the json file in the same directory (sibling to package.json and app.js).
I had tried process.env.GOOGLE_APPLICATION_CREDENTIALS = "./key.json"; in my app.js file (using express), but it isn't working. I have also tried putting "GOOGLE_APPLICATION_CREDENTIALS":"./key.json" in my package.json and that didn't work as well. It DOES work when I run in the terminal export GOOGLE_APPLICATION_CREDENTIALS="./key".
Here is the error message:
ERROR: Error: Unexpected error while acquiring application default credentials: Could not load the default credentials. Browse to https://developers.google.com/accounts/docs/application-default-credentials for more information.
Any tips are appreciated, thanks!
After reading and reading about this issue on the internet, the only way to resolve this issue for me was to declare the environment variable for the node execution:
GOOGLE_APPLICATION_CREDENTIALS="./key.json" node index.js
Because I was able to print the token from my server console, but when I was running the node application, the library was unable to retrieve the system environment value, but setting the variable for the execution, it was able to retrieve the value.
It could be that the environment variable in your OS was not accurately set. For example in Linux you usually have to set GOOGLE_APPLICATION_CREDENTIALS in the terminal where you executed your app.
export GOOGLE_APPLICATION_CREDENTIALS="[PATH]"
Another option you have is passing the json path by code. It is documented this process using Node.js with the Cloud Storage.
Just to update this thread.
Relative paths with GOOGLE_APPLICATION_CREDENTIALS now works fine with dotenv :)
Just store your service-account credentials as a file in your project and reference it relative to your env-file as a path. Then it should work fine :)
I encountered the same issue. I was able to get it working by doing the following:
export GOOGLE_APPLICATION_CREDENTIALS="//Users/username/projects/projectname/the.json"
The issue is covered mostly in the docs here.
the command varies slightly depending on what your OS is:
The GOOGLE_APPLICATION_DEFAULT environment variable you are setting is accessed by the google client libraries - it wont work with a relative path, you'll need to set the absolute path.

Where should I store cache of a custom CLI npm module?

I am developing an npm module, where user can interact with it through a terminal by executing commands:
> mymodule init
> mymodule do stuff
When executing certain commands user is being asked for some data, which will be used by the module. Since this data won't really change while using the module and since these commands can be executed pretty frequently, it is not the best option to ask user for the data any time he runs a command. So I've decided to cache this data, and as soon as it should live through multiple module calls, the easiest way to store it that I see is a file (the data structure allows to store it in a simple JSON). But I am to quite sure where should this file go on a user's machine.
Where in the file system should I store a cache in a form of a file or multiple files for a custom npm module, considering that the module itself can be installed globally, on multiple operation systems and can be used in multiple projects at the same time?
I was thinking about storing it in a module's folder, but it might be tricky in case of global installation + multi-project use. The second idea was to store it in OS specific tmp storage, but I am not quite sure about it too. I am also wondering if there are some alternatives to file storage in this case.
I would create a hidden folder in the user's home directory (starting with a dot). For instance, /home/user/.mymodule/config.cfg. The user's home directory isn't going anywhere, and the dot will make sure it's out of the user's way unless they go looking for it.
This is the standard way that most software stores user configs, including SSH, Bash, Nano, Wine, Ruby, Gimp, and even NPM itself.
On some systems you can cache to ~/.cache by create a sub-directory to store your cache data, though its much more common for applications to create a hidden directory in the users home directory. On modern windows machines you can use create a directory in C:/Users/someUser/AppData. In Windows using a . suffix will not hide a file. I'd recommend you do something platform agnostic like so:
var path = require('path');
function getAppDir(appName, cb) {
var plat = process.platform;
var homeDir = process.env[(plat == 'win32') ? 'USERPROFILE' : 'HOME'];
var appDir;
if(plat == 'win32') {
appDir = path.join(homeDir, 'AppData', appName);
}
else {
appDir = path.join(homeDir, '.' + appName);
}
fs.mkdir(appDir, function(err) {
if(err) return cb(err);
cb(null, appDir);
})
}
Just declare a function to get the app directory. This should handle most systems, but if you run into a case where it does not it should be easy to fix because you can just create some kind of alternate logic here. Lets say you want to allow a user to specify a custom location for app data in a config file later on, you could easily add that logic. For now this should suite most of your cases for most all Unix/Linux systems and Windows Vista and up.
Storing in system temp folder, depending on the system, your cache could be lost on an interval(cron) or on reboot. Using the global install path would lead to some issues. If you need this data to be unique per project, then you can extend that functionality to allow you to store this data in the project root, but not the module root. It would be best not to store it in the module root, even if its just installed as a local/project module, because then the user doesn't have the ability to include this folder in their repositories without including the entire module.
So in the event that you need to store this cached data relevant to a project, then you should do so in the project root not the node_modules. Otherwise store it in the users home directory in a system agnostic way.
First you need to know in what kind of SO you are running:
Your original idea is not bad, because global modules are not really global in all SO and in all virtual enviroments.
Using /home/user may not work in Windows. In windows you have to check process.ENV.HOMEPAHT
I recommend you a chain of checks to determine the best place.
Let the user take the control. Chose your own env variable. Supouse MYMOD_HOME. You firts check if process.ENV.MYMOD_HOME exists, and use it
Check if windows standard process.ENV.LOCALAPPDATA
Check if windows standard process.ENV.HOMEPATH
Check if exists '/home/user' or '~'
Otherwise use __dirname
In all cases create a directory ./mymodule

Resources