I'm using the framework Yii2 for the first time and I was wondering if it is secure to write in plain text my database's password in config\db.php? Or is their a more secure way to access to the database?
It should be secure enough as long you are not exposing this file to public users.
You can store it anywhere on the server basically (as long as it's not exposed to public users) but application should be able to get it fast and easy (to not provide additional delay for the database connection).
If you are using Git, I believe it is a bad idea to commit any file with a password in it. Personally I keep a separate file with a few crucial passwords outside of Git and load that file in to get the values, like this...
$ini = parse_ini_file('path/passwords.ini', true);
return [
'class' => 'yii\db\Connection',
'dsn' => $config['db']['dsn'],
'username' => $config['db']['username'],
'password' => $config['db']['password'],
'charset' => 'utf8',
];
Where passwords.ini would look like...
// My password file
[db]
dsn="mysql:host=localhost;dbname=xxx"
username="xxx"
password="xxx"
You could leave db.php out of Git, but I find this more convenient, especially for other config-files where many settings does not affect security.
I don't know why you created an extra file. In your common\config folder,you will get main-local.php. You can define your Connection credentials in there.
By default that file will be ignored by git.
Related
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.
I want to know why there isn't an easy way to load your security keys from the AppSettings.json instead of loading them off the file system as XML?
Here is the example from the Microsoft documentation.
services.AddDataProtection()
.PersistKeysToFileSystem("{PATH TO COMMON KEY RING FOLDER}")
.SetApplicationName("SharedCookieApp");
services.ConfigureApplicationCookie(options => {
options.Cookie.Name = ".AspNet.SharedCookie";
options.Cookie.Path = "/";
});
I'm just wondering why there isn't something like the following.
services.AddDataProtection()
.PersistKeysToAppSetings("EncryptionKeys")
.SetApplicationName("SharedCookieApp");
services.ConfigureApplicationCookie(options => {
options.Cookie.Name = ".AspNet.SharedCookie";
options.Cookie.Path = "/";
});
I don't understand why storing keys in an XML file would be any different than storing them in your AppSettigs.json. Now I know the format is different, however it's no more or less secure? correct?
I just want to be sure I'm not missing something.
Assumptions:
AppSettings.json is just as secure as some other XML file on disk
Azure AppSettings are securely stored and can only be access by permitted accounts
Azure AppSettings values would override any uploaded "developer" values
Developers will not store their production keys in source, surely right? :)
I know this would not work for expiring / recycling keys
"It's complicated"
We create keys on demand.
We create multiple keys, just before a key expires, we create a new one.
We need keys to be synchronized between applications.
We need keys to be encrypted where possible.
AppSettings does not give us any of those things, applications can't update their own settings files so that rules out 1 and 2, web sites don't copy a changed app settings file between instances which rules out 3, and you can't encrypt things in app settings which rules out 4.
The format isn't the problem, you could write your own encryption wrapper to cope with #4, but the rest is still necessary, so now you have to change how settings works so they're read/write (and safely read write), and then persuade web hosts to support synchronization of your custom settings file between instances.
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.
I tried accessing data with FileZilla and additionally downloading it. This worked. However, now I tried accessing the same file with the same user with nodeJS with "GET". Here I get the Error "Access Denied".
I looked into the permissions, and the owner and group of the file are able to read and write the file, but no public permissions. My user is part of the "Group". However, I am now wondering, if the file needs to have public permissions to read and write in order to access the file via nodeJs?
Quick Info: I access the file both with FileZilla and NodeJS via SFTP. All configs / user etc. are the same.
Code:
let Client = require('ssh2-sftp-client');
let sftp = new Client();
sftp.connect({
host: config.development.host,
port: config.development.port,
username: config.development.username,
password: config.development.password
}).then(() => {
return sftp.get(`${config.development.pathToFile}/${filename}`);
}).then(async (data) => {
console.log('data', data);
csv({
noheader: true,
output: "csv"
})
Thanks!
Does NodeJs needs public file permissons to access file?
As long as the user that spawned the Node.js process has read permissions for the specific file, you shouldn't encounter any problems.
I would suggest learning how multi-user environments & permissions management works.
Recommended reading :
Learning the shell - Lesson 9: Permissions
Linux Tutorial - 8. Understand Permissions
Recommended further reading :
The default Linux security model is a bit inflexible. To give special
access (such as modification privileges) to a group of people, you
have to get your system administrator to create a group with those
people in it. Furthermore, if you would like to give a different set
of access privileges (such as read access) to another group of people,
you can’t do it because you can only assign one group owner per file
or directory. To solve this problem, you can use ACLs (Access Control
Lists). You can learn more about them from this link: ACLs
(Quote extracted from here)
After all, it will come in handy and it wont take you much effort to understand.
I am creating a NodeJS API server that will be delegatiing authentication to an oauth2 server. While I could store the key and secret along with the source code, I want to avoid doing that since it feels like a security risk and it is something that doesn't match the lifespan of a server implementation update (key/secret refresh will likely happen more often).
I could store it in a database or a maybe a transient json file, but I would like to know what are the considered the best practices in the NodeJS world or what is considered acceptable. Any suggestions are appreciated.
One option would be to set environment variables as part of your deployment and then access them in the code from the global process object:
var clientId = process.env.CLIENT_ID
var clientSecret = process.env.CLIENT_SECRET
Since I wanted to provide something that can store multiple values, I just created a JSON file and then read that into a module I called keystore (using ES6 class):
class KeyStore {
load() {
// load the json file from a location specified in the config
// or process.env.MYSERVER_KEYSTORE
}
get (keyname) {
// return the key I am looking for
}
}
module.exports = new KeyStore();
I would ideally want to store the file encrypted, but for now I am just storing it read only to the current user in the home directory.
If there is another way, that is considered 'better', then I am open to that.