I am working on a MySQL project website with the goal that it could be implemented in several local companies in order to keep track of some information (note this is a project for a college course). My question is about the best way to use a similar structure that can keep each company's info private from the others.
Assume I have 3 different companies, each requiring a database to store Employees, Projects, and Messages, or 3 DBs per company.
My current plan is to create 10 total databases: 3 of the 3 required databases for a total of 9. These DBs would have a prefix to their name to differentiate them (e.g. CompanyA_employees, CompanyB_employees, CompanyC_employees, etc.) I would then use the 10th DB to store the company names and their respective prefixes. Is this a good way to do this, or is there a better way?
Also, I am also thinking to give each DB its own user (again, it would be prefixed) with its own unique password. This would be the username and password that is used in a PHP script to access the DBs and SELECT, INSERT, etc. My hope is that this would make it difficult for someone to compromise more than 1 DB at a time, or for companies to be able to access each others' sensitive information. In addition, these users would only be given the bare minimum permissions to the DB, to further guard against things getting fubar'd.
I would store the DB users' passwords (SHA256 or SHA512 hashed with salt, of course) in that 10th DB. If this is a good design, is there a better (but still secure) way to obtain these passwords than querying the 10th DB every time I need to access one of the other DBs? I'm assuming storing them in a cookie is a bad idea security-wise.
Any suggestions are appreciated, as I am relatively new to securing MySQL DBs.
First off, you want to define more of a role that the databases are going to serve.
It really depends on the magnitude of the information expected to be held if you should have one database per company or one master database.
Note that most web hosts would not allow you to host 1000+ databases unless you are running your own dedicated database server. Cost definitely becomes a factor there.
For Employees, Projects, and Messages, one database should be sufficient.
Using the web interface, you only need the single database-user for the website itself to connect to the database. It is then up to how your website handles the website-user logins and what data each user has access to.
So for this you need to create a website-user-table in the database that handles the user login information, timeouts, intruder detection, and what information in the database that user has access to.
For each table of information, for example, you can have a single column with a unique company ID. Your website then allows a user that belongs to that company to see the information for that company and no other.
So your tables for the database will probably be:
---------
Web_Users
Company
Employees
Projects
Messages
---------
With the Web_users, Employees, Projects, and Messages tables linking to Company table using a foreign key.
This setup keeps your database secure because only your website can access it, and only those who can log into your website can then access information--only the information that belongs to the company that the user belongs to.
This puts the majority of the security burden on how well you write the website interface.
Hope this helps!
Related
I have an application in which we want to provide the functionality using which user can add/update/delete the columns of different tables. My approach is to create a different database for each client so that their changes specific to tables will remain in their database.
Since each client will have their own database, I wonder how can I manage authentication and authorization? Do I need to create a different database for that as well? Will it affect the performance of the application?
Edit: The approach that I am planning to use for authentication and authorization is to create an additional field called "Account" on the login page. This account name will guide the program to connect it to correct database. And each database will have it's own users to authenticate.
The answer to your question is of course (and unfortunately) Yes and No. :)
This is known as multi-tenant data architecture.
Having separate databases can definitely be a great design option however so can using one database shared with all of your clients/customers and you will need to consider many factors before choosing.
Each design has pluses and minuses.
Here are your 3 essential choices
1) Each customer shares the same database and database tables.
2) Each customer shares the same database but they get their own schema inside the database so they each get their own set of tables.
3)Each customer gets their own database.
One major benefit (that I really like) to the separate database approach is data security. What I mean by this is that every customer gets their own database and because of this they will edit/update/delete just their database. Because of this, there is no risk in end users overriding other users data either due to programmatic error on your part or due to a security breach in your application.
When all users are in the same database you could accidentally pull and expose another customers data. Or, worse, you could expose a primary key to a record on screen and forget to secure it appropriately and a power user could override this key very easily to a key that belongs to another customer thus exposing another clients data.
However, lets say that all of your customers are actually subsidieries of 1 large company and you need to roll up financials every day/week/month/year etc.
If this is the case, then having a database for every client could be a reporting nightmare and having everyone in a single database sharing tables would just make life so much easier. When it comes time to report on your daily sales for instance, its easier to just sum up a column then go to 10,000 databases and sum them up. :)
So the answer definitely depends on your applicaton and what it will be doing.
I work on a large enterprise system where we have tens of thousands of clients in the same database and in order to support this we took very great care to secure all of our data very carefully.
I also work on a side project in my spare time which supports a database per customer multi-tenant architecture.
So, consider what your application will do, how you will backup your data, do you need to roll up data etc and this will help you decide.
Heres a grea article on MSDN for this:
https://msdn.microsoft.com/en-us/library/aa479086.aspx
Regarding your question about authentication.
Yes, having a separate database for authentication is a great design. When a customer authenticates, you will authenticate them off of your authentication database and they will receive the connectionstring to their database as part of this authentication. Then all data from that point comes from that clients database.
Hope this was helpful.
Good luck!
Our client would like the user table to be separated from all other tables for "security reasons". Is this a good practice given that our application is built using RoR and MySQL and running on Unicorn and Nginx ?
I can think of two possible ways:
Create two different login accounts, one for the user table and one for the other tables.
OR
Have a separate database for the user data.
I think that both the solutions might create some problems with the migrations and other tasks and I don't know if this is an effective method of protecting user data. I am a junior developer and I am not familiar with some database and security concepts. Any suggestion?
A very common pattern is to have the users table literally just contain details of the user account and NO details of the actual person behind that account. ie, it would have username, email, password, or encrypted password & salt or whatever, but nothing else - not even name. So, all the "glue" that makes the system work stays in the users table in your regular database.
Then, the details of the real person behind the account (name, telephone number, address, card details etc etc) are stored in a different table, or tables, with a foreign key in either table pointing into the other one. You could store them in a different database but i don't know if this makes it more secure. A better way might be to encrypt just the table with the user's personal data, or perhaps encrypt the entire database. see
http://thinkdiff.net/mysql/encrypt-mysql-data-using-aes-techniques/
I get the feeling that your client doesn't know a lot about internet security and just needs to be reassured that some hacker isn't going to put all the customers' credit card details online, as has happened in several high profile cases recently. To satisfy them i would recommend that you research this well and implement at least two different security strategies, each of which on their own would be considered adequate.
Reassuring the client didn't work as this was an acceptance criteria for launch. In the end, I created two separate database with separate login credentials and user permissions. In order to manage multiple database migrations, I initially used multi-database-migrations gem and then customised it into my own gem.
I was new to SO when I posted this question (still am) and I now understand that the topic is too wide to be asked in a single SO question. Thanks for the suggestions anyway and I hope that the answer can help other people.
Unfortunately this question may be a little broad, because I can't work out the proper terms to help me bring all this together. I'm very new to php/SQL, and I'm attempting to set up a minimal site with very simple login/register functionality.
Should I be creating a new database user whenever I register a new web user?
Are CRUD privileges safe to give to all users of the website?
Should I actually make a DB user for registering, one which can only insert into the user table and nothing else until they login (requiring no password for mysqli_connect())?
Once logged in, they would make a connection to a different type of DB user, one with more privileges to use the website.
How many different types of DB users should there be?
I assume a small group of users for the DB workers (including one for root access), another group for each type of web user (ie. employers have more privileges than employees), and another restricted user just for registering.
All in all, would >10 DB users in a small website be unusual?
Is there a performance/space cost associated with having many types of users?
I appreciate any responses and links, and apologize if these are very basic questions.
I struggled with this all those years ago, so here is the answer I wish I had:
Generally, this is overcomplicating things, and the headline answer for a basic application is: the permissions of users will be managed by the PHP code in the API calls you make, and one DB user is fine. All users should avoid interacting directly with the DB for app dev generally, to prevent violating the sanctity of the data.
It's good to think about security and restrictions, but simplicity is king - the more complex you make it, the harder it is to maintain, and therefore the easier it is to miss corner cases.
Should I be creating a new database user whenever I register a new web user?
No, database users are distinguished by their privileges. As a result, all users conform to a set of groups with varying privilege levels. The database accounts are separate from the web accounts - connecting to the database is done behind the scenes and has no link to the web account being used.
A good approach would be to create a DB account for each service connecting directly to the DB. For the vast majority, this will be one service, your web server. If the application grows and isolated services such as audits, microservices, security, IOT spring up, they should probably have their own accounts.
Are CRUD privileges safe to give to all users of the website?
The question is misguided - you give the CRUD to the DB account, which will need it. For the CRUD permissions managed inside the PHP, it really depends on your app and specific endpoints. For example, you probably don't want all your users to be able to delete User records, so your PHP code should prevent that from happening.
How many different types of DB users should there be?
The number depends on your database. Generally, there are 4 groups
Database Administrators
Database Designers
Casual End Users
Native End Users
However, if you want to grant table level privileges then you might need to branch out a little more. This would suggest 10 DB accounts is quite a small amount, several hundred is more likely.
The more privileges, the more space is required, but it's a fairly minute consideration, and shouldn't play a big role in performance. Complexity is the next issue - think carefully how many groups and permutations you actually want to test. In the case of the question above, I was a single hobbyist developer - one account as a DBA is probably fine. If there were multiple users directly accessing the DB (already probably a bad idea for app dev), then maybe split out them with varying permissions.
Talking about table level permissions for a simple app is just way overkill!
I am working on a web application that will require users to have their own set of private data. My original plan was to create a stores table, a users table, and a user_stores intersecting table. Then I would, in the stores table, save the database name for that store (and create each store-specific database with an application user and password so the web application could always login).
Each store would have similar data (users, products, shipping methods, etc), and I know I can use foreign key references to tie everything together in one giant database. However, being that the data is very specific and potentially proprietary, would it be better to use my original design, or make a single database with everyone's data in there?
I am thinking for scaling concerns, separate databases would be better because we could put the more active accounts on their own (or more powerful) database servers and simply add a server location field in the stores table if we needed to. Additionally, it may be more secure because we could make add the user login information to the database and only give them access to their data (preventing one user from editing another user's stuff). My question is, are there concerns that I am missing though? Just about every post I have read about this says not to use the method I am thinking of, and I am no DBA. Any input would be helpful.
Additional Information:
This will be hosted on a Dedicated Server that I will have root access to. I can create as many MySQL databases as I need to.
I would use a single database for sure. Use the following to get started. There are several reasons to go with a single db, however the biggest reason of all is to save you from a maintenance nightmare. If you have to change the schema, you will have a mess on your hands.
http://msdn.microsoft.com/en-us/library/aa479086.aspx
In a multi-tenant database, database designers think about querying, cost, data isolation and protection, maintenance, and disaster recovery.
Multi-tenant solutions range from one database per tenant ("shared nothing") to one row per tenant ("shared everything"). This SO answer summarizes the tradeoffs. If you're designing a database that falls under some kind of regulatory environment (HIPAA, FERPA, etc.), that regulatory environment might trump all other considerations.
One database per tenant is a defensible decision in some cases. It's not clear whether that's the best answer in your case, though.
What I am trying to ask is ...
Users will only ever access the database via my application. The application itself allows an admin user to create/modify/delete users and give them certain privileges. So, I have a table which contains each users log-in name & password.
I am still developing the app, so it currently logs in as root with no password. Obviously, I will change that, but what's the best practise? Should I have a single database user & password which the application uses, or should I create a separate user for the databaase each time a user for the application is created (or modified)? The latter seems like more work.
Your APPLICATION should certainly have separate user ids and passwords for each user. Given that, there's no reason for the application to have multiple user ids when it talks to the database. As long as the application's security is implemented correctly, there's no gain from having multiple DB user ids.
Giving each user his own DB user id would surely be a gigantic pain because it would likely involve all sorts of special cases and exceptions. For example, to log in to your application, the application would have to validate the user's id and password. How will it do that if the user doesn't have access to the password table? But if anything needs to be protected from unauthorized access, it's the password table. So you'd have to use one userid to do the login, then take that away and give a different userid. It's likely that there are other tables that a given user might be allowed to access in one context but not in another. The accounting department likely needs to see total amounts paid in salaries for the year, but maybe they can't see individual employee's salaries. Employees may be able to access data about their own benefit, but not that of other employees. Etc.
The only exception I can think of to this would be if you allowed some sort of generic access to the database. To take the most extreme case, if you had a screen where the user can type in an arbitrary SQL query which you would then execute. In that case, you could theoretically have the application analyze the query and attempt to apply security rules, but that would require your application to embed an awful lot of knowledge about SQL. In that case you'd be better to give each user his own DB user id and putting the security rules into the database engine.
Short Answer: Before the internet, yes. After the internet: nobody does it, but it is still perfectly acceptable.
Common practice in the internet age is to consider your application to be the user, and to give that application a login. The only actual benefit is some performance boost from connection pooling. The perceived but illusory benefit is security.
Understanding the security angle requires the realization that all security in the end resolves down to who can read and write from what tables, rows and columns. To see how this works, consider a user who is authorized to manipulate a highly secure table, and another user who cannot even see that table. The less privileged user successfully manages a SQL injection attack attempting to wipe out the secure table, it fails because the Database prevents access by that user to that table.
The takeaway is that there is no technical reason to use a single login except if connection pooling is important. Databases are very poorly understood by many internet age programmers so explaining how to use their built-in security is an uphill battle against many pre-conceived and incorrect ideas.
There's no reason to create a database login for each user. It's really your app that's interacting with the database, not the user. Creating extra logins just makes your database that much less secure.