I have read many posts and articles that state quite clearly that for the best in worst-case damage limitation, MySQL accounts should only be able to do what they're intended to do, and nothing else. This makes perfect sense and so there would be a connection account to my Database that does all the SELECTing of data, and another account that does UPDATE and INSERT activities, so that if someone does get the compromise by SELECTing data they shouldn't, then they can't quite as easily then UPDATE that data or INSERT etc.
You get the idea.
But, I have various Databases and use accounts to read/SELECT data and the this is output to the client page, but often these accounts will need to be updated, small things such as updating when a (website) user logs into their account, or updating some sort of hitcounter or other minor feature. Given the ringfencing of concerns outlined above, I feel it's a bit like using a flood to put out a campfire, to allow UPDATEing (etc.) to a privileged MySQL connection simply to say that user Bob logged in last at 4:10pm.
I have been digging on the web for suitable guides, blog posts and articles about how to best structure using multiple MySQL privileged accounts to complete the nessecary work with as minimum a risk of excess privilege as possible, but I have found nothing that has been much use, (mostly because of my wording seems to be attracting articles about setting up website users, or other topics associated with these keywords :-/ )
I have a few ideas on current approach and wanted a bit of feedback on the best method for doing activities as described in paragraph 2, typically 95% SELECTing, and a few specific instances of UPDATEing, or if any of the following are possible (or on flipside, are very bad ideas)? :
I currently have seperate PHP connection objects for each connection privilege user. Is this the best approach?
Could I somehow giving a privilege user access to only update a certain table (or even a certain table column?), as well as SELECT from any table? This would be perfect.
Are using TRIGGERs a common approach and would this have any down sides if I created a Trigger (with a privileged user) and then let a SELECT user account access triggers?
Could I set certain users can only use certain triggers?
Is there another way of doing this?
MySQL allows for users to have different privileges set both at database and individual table levels. The documentation on the GRANT (http://dev.mysql.com/doc/refman/5.7/en/grant.html) syntax gives an example of setting all privileges to a user on one database while only select access to a table in another database.
Privileges can even be set for specific columns (http://dev.mysql.com/doc/refman/5.7/en/grant.html#grant-column-privileges) in a table & also for stored procedures (http://dev.mysql.com/doc/refman/5.7/en/grant.html#grant-routine-privileges).
Related
I am making a web application where users get and manage data from multiple tables as well as create other users to access said data. currently I have it set up for one group of users.
My question is would it be better to have multiple databases in which each database has its own user which is stored in a master table("I don't like the sound of this one") or have a column in each table defining the user group that has access to it? Are either of these a good idea or is something else more appropriate?
You should have a column in each table. In my opinion, its the correct thing to do, and also you have only one database to do mantainance.
Just imagine the time it would take to add a column to a table in the future, and you should do it in multiple databases.
Currently, in my app there are just 3 roles visitors can have:
admin that has all privileges
user that can can perform several actions about him/her-self within the system
guest that can just watch and send bug reports
Everything is primitively implemented, as follows: in a DB each user has a field where his being admin (stands for 2 in the field) or user (1) is indicated, and in the application_controller.rb it is just checked if logged_in? && current_user.DB_FIELD == 2 (or > 0), and in the necessary controller there occurs a before_filter check, etc.
However, such a simple implementation worked great till recently when we decided to extend the functionality of the system, that is, partly, to allow admin to join users into groups, but there are some moments. For better understanging of what I am going to ask, let me describe the situation from the way I see it (maybe you can suggest something much better and logical):
I am an admin. I open /groups, and see a list of groups.
What is a group? A group, on the one hand, is a set of permissions, and on the other hand, is a combination of users that should have the same permissions within my app.
What is a permission? A permission is one action that each user of the group it assigned to can perform.
I want to unite new users in one group, but this group doesn't exist. So I click the button (which stands for /groups/new), and the Create Group window pops up. There, I have a textfield for a group name, a bulk of checkboxes, each stands for a permission, a field for adding users, and a Save button. I write the group name, check all the permissions I want to assign to this group, add users to this group (I am going to implement this through ajax search: starting typing a user's name, he/she appears, click Enter, and one user is added, then repeat these actions if needed - is it an OK approach?), and click Save.
Ok, I got a new group with several users. But stop, I realized I forgot to add one more person! I return to the Edit Group window (/groups/edit), and refill the misfilled fields. Click Save - and again some magic (I mean, update operations over the DB).
And so, what I have at the final stage? I can freely c/r/u/d the groups, managing users and permissions in them, and perform it in a very GUI-driven way (I mean, checkboxes, ajax search field, etc.)
For two weeks I have been googling/stackoverflowing/scrutinizing info about rails role- and group-based authorizations; have found a lot of solutions like cancan, easy_roles, troles, etc. gems, but cannot find in any of them how to implement a group-based approach, which is dynamic (or customizable? or dynamically customizable?). The only thing that really 100% suits my needs is a redmine permission and permission group approach, but it is overcomplicated due to its over9000-functionality, so I couldn't even fully understand how it is implemented, let alone implement it on my own.
And the questions are (assuming that the set of permissions is permanent so can be hardcoded, and the set of groups is absolutely free; also, if the user doesn't belong to any group he/she has default user permissions; moreover, permissions are not just for c/r/u/d operations, but also for the manually created methods):
What is the best way to implement the above mentioned system? Any existing yet not found by me gem or approach?
How to painlessly-for-scalability store the permissions and the permission groups? A bitmask, or separate permission, permission-to-group assignment, and group tables?
How to painlessly put users into groups? A group field in the user's DB row, or a separate user-to-group assignment table?
Preferably, that the permissions assigned to the group the user being added to, instantly, without any user relogins, apply to him.
Thank you in advanced!
Through several nights I finally came to a solution, which is, to my mind, rather easy yet powerful, but obviously not the best (but still an) implementation.
So, we have now +1 tables, which is of groups, where the columns are id, name, and permission. The last column is a usual integer which represents all the permissions in a decimal number.
The permissions are "aliased" in the controller: e.g. 1 stands for can_manage_smth, 2 stands for can_view_smth, etc.
The permission choice panel is in the /groups section, and is a simple set of checkboxes, applying an onchange action to each we ajaxly perform an OR operation with the permission stored in the table (e.g. we select 3 checkboxes standing for the values of 1, 8, and 16, then we get in our table 25, which is, in turn, a result of 1 | 8 | 16).
So answering my questions:
Not the best but still a solution.
It almost does not affect the scalability because adding a new permission (which is a very rare action) will just demand a new alias of the permission and its before_filter checkings in the beginning of the controller. And I used a bitmask but not as a binary but just a usual decimal value with which simple binary logic operands can play.
No separate user-to-group assignment tables, just a single group_id column in a user table (which already existed).
Hope everything implemented will work perfectly. If any issues occur, I will indicate here. Also, if any new implementation ideas come.
Anyway, thanks to everybody!
I currently have two tables. One is accounts and one is tbl_units_info. My boss wants me to make it so that accounts are restricted from reading certain rows in a table. Frankly, I think my boss has no idea what he is talking about, but I'm hoping someone here can prove me wrong.
For example, accountname krikara can only view the entries of the tbl_units_info table where the TBID column is 0909.
Is this even possible? To make krikara only able to view the rows in that table where column TBID = 0909?
It can not be implemented plainly on DBMS level since SELECT privilege has table level. You can not restrict rows reading. And this is good, I think - because data could be changed, so in general there is no solid condition for rows restriction (and, therefore, there could not be valid implementation for that on DBMS level).
You can, however, use VIEW - but it is a middlepoint, not common solution (I still not think it will help with tracking rows changes, but may be I'm wrong due to your application logic)
You can try to implement it in your application, but it still has problem I've described above: in table, data is changing. You'll probably have troubles with tracking all changes. I think you can separate your rows on two (several) tables and then build your permissions model. But - if some basically similar entities must have different permissions - probably you should reconsider application security model?
You could solve it by giving accounts just the reading rights to a view instead of the whole table.
CREATE VIEW `tbl_units_info_krikara` AS
SELECT * FROM `tbl_units_ino` WHERE `TBID`='0909';
And then assign the respective rights to your user.
MySQL CREATE VIEW documentation
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
My app involves implementing data and displaying it to the user.i'll give you a full explanation of the app and what i'm trying to achieve.
Basically the app finds out what car is best suited for the user. last week i decided that a drop down menu will be easier and more interactive than a normal questionnaire. i have three labels, performance, luxury, eco friendly and three buttons, high performance, high luxury and high eco friendly. how can i add data to these so that when the user picks these preferences, it links to a specific car, let me remind you that this is just one of many controllers and questions.
I read that MYSQL is good but I'm not sure if its easier or harder. To be honest, im still in beginner level for programming. Also some linking and database videos on youtube are a joke.
I'll try to get you more on track. Your question shows that you're a newbie but if you're a newbie with some sense you'll catch on instead of complain.
MySQL is a variant of SQL. Unfortunately Oracle (evil Microsoft of the business world--think vendor lock-in) bought out Sun Microsystems (a not evil corporation that should have been defended to the death or close-to). There is some political concern that MySQL is slowly being closed off in favor of Oracle so if you have the option opt for PostgreSQL.
With a database you have two things: a database and a user.
The database part is easy, that is where information is stored.
The user part is still pretty easy, different users have different permissions. Those permissions in example are what SQL commands can be executed.
A database's structure is basically....
Database --> Table --> Columns/Rows
A database table is like an HTML table, columns are sets of data (a 'name' column, an 'address' column, etc). Each row is an entry. Bob's information may be on row 34, Sally's information on row 35, etc.
The four most common commands you'll use: SELECT, INSERT, DELETE and UPDATE. With my software unless a webmaster is signed in a lower level privileged SQL user only has access to these four base SQL commands.
There are two contexts to working with SQL: building it and using it. I'm not an expert though what I've generally accepted is that using SQL across different variants (e.g. MySQL and PostgreSQL) for day-to-day use (accessing, updating, removing, editing data) utilizes standardized SQL commands. Sure, some companies may change the structure of their database on a daily or even hourly basis ON a regular basis but generally speaking not everyone. Commands to change a database structure such as ALTER may NOT be cross-variant standard. Why does this matter? If you don't understand the politics of what is involved then YOU DO NOT UNDERSTAND WHAT IS INVOLVED. So I've made sure I'll be able to easily migrate from MySQL to PostgreSQL by avoiding vendor specific syntax. Spend an extra 20% doing things right the first time and you'll save 80% of the time wasted on maintenance by everyone else.
If you want jump in and start using MySQL get a copy of XAMPP. It takes minimal effort and is great for LOCAL testing (local means YOUR computer only accessible to you/your LAN, live means available on the web in general). I'm not sure about xcode but the general instructions should at least give you a basic guide to stay on track in regards to databases.
If you're looking to learn with a GUI you'll want to use phpMyAdmin (included with XAMPP) though I don't recommend downloading the latest copy as they're going way overboard with some things in phpMyAdmin. PostgreSQL has it's equivalent. It'll show you working (albeit VERY messy) examples of commands. For your reference here are some commands I use in the console...
The highest privileged user in SQL is usually called 'root' (without quotes). You'll have root access on your localhost (local) and dedicated servers (likely VPS too) though not on shared servers unless you're some kind of 1337 haxorz.
The four most common commands...
Using SELECT to retrieve data...
SELECT * FROM database_table;
SELECT id, name FROM database_table WHERE cool_factor='exact matching text';
Using DELETE to remove a record...
DELETE FROM database_table WHERE id='1';
Using INSERT to add a single new record...
INSERT INTO email_filters (age, name) VALUES ('Bob');
Using INSERT to add multiple new records...
INSERT INTO email_filters (name) VALUES ('Bob','23'), ('Sally','24'), ('Susan','25'), ('Irate Yeti','9001');
Using UPDATE to update an existing record...
UPDATE accounts SET name='Mr. Yeti', profession='eating people' WHERE id='234';
BTW it's common practice to make your syntax uppercase to differentiate between SOL-specific syntax and your content.
Important commands that help you create and get around in SQL...m
Login: this will prompt you for a password...
mysql -uroot -p
Show a list of databases (phpMyAdmin will let you create databases)...
show databases;
Select a database to work with...
USE mysql;
Select an SQL user...
SELECT User FROM user;
SELECT User FROM mysql.user;
Create a user (with a normal and admin example)...
CREATE USER 'example_v10'#'localhost' IDENTIFIED BY 'my_!1337_p#ss';
CREATE USER 'example_v10a'#'localhost' IDENTIFIED BY 'my_!1337_p#ss';
Before an SQL user can access a database it must be granted permission, here is a limited permission example...
GRANT SELECT, INSERT, UPDATE, DELETE ON `example_mysite_database`.* TO 'example_v10'#'localhost';
...and an administrative user being granted all permissions (use with caution)...
GRANT ALL PRIVILEGES ON `example_mysite_database`.* TO 'example_v10a'#'localhost';
Import an SQL file in to an existing database...
SOURCE C:\path1\path2\the.sql
Describe a database...
DESCRIBE table_name;
Change an SQL user's password...
SET PASSWORD FOR 'root'#'localhost' = PASSWORD('lulz_bad_password');
It's VERY important to realize in the long run that you'll be COMPOSING SQL queries, you NEVER dump them in a loop. Your goal is to make larger more elegant SQL queries that do more in fewer queries if not a single query whenever possible. In example a typical page request on my site's software utilizes about eight~12 queries subjective to the section/page/permissions/etc. Poorly written software like WordPress will utilize dozens if not more requests.
You will absolutely not be able to do anything effectively with databases without learning how to do RELATIONAL SQL; that is just fancy way of saying you know how to use INNER JOIN and LEFT JOIN (and some people use OUTER JOIN). A JOIN allows you to store a piece of information in the entire database once, like an account name. If you build a forum and want to pull forum posts you would JOIN the user accounts table and simply pull the user names by dynamically referencing them, you wouldn't actually store their user name every single time. However that is for another day. I learned SQL over a couple months and once I learned relational SQL I exploded making a blog in three weeks, a forum in a month, a chat room in three weeks, etc.
Feel free to use this as a cheat-sheet and give you some sense in how to reference some technical jargon. when you ask questions you need to be as concise and accurate with terminology as possible. Asking extremely large questions (how can I make a facebook without doing any work?) is bad, asking a specific question is good (How do I have my programming language connect to a database with a specific user that has limited privileges?)
The table names are variable, but what is certain is that SELECT only is allowed and certain tables are excluded (ie Users, Log). I'm making a reporting form where a user can just enter sql queries to make template reports.
SELECT 'field1' As 'foo', 'field2' as 'bar'.. 'fieldn'
FROM 'table1',..'tablen'
JOIN ... ON ...
WHERE CONDITION
Although I'm thinking I can have the table names in a html select list of existing tables.
Also make a user reporter_appname#localhost with SELECT access only to all tables except Users and Log? In that case I won't need to bother with a regex check of the query?
(This would be in PHP)
(Ideally I just wanted a single textarea where the admin can just type their query, my report function would then take the output and present it nicely etc.)
I suggest you re-think your design.
Identifying valid select statements (and excluding all other statements) is basically impossible without completely parsing SQL. A regex is not going to be up to the task.
Even if you allow only select statements, users could perform denial-of-service attacks on your database. It is very easy to create select statements that run forever (we've all done it). A malicious user could crash your site in a hurry. And even well-intentioned users might do this by accident.
It would be much better to give the users more limited options for creating reports. Let them select certain tables and columns from a list, and create the appropriate query for them.
There is probably free MySQL reporting software out there that could serve as a good starting point, though I don't have any experience with this myself.
I think that you should rethink the design of your application.
The Users and Log tables should be on one database and the tables with the data for the reports should be on another database.
If you have them all in one database already just create another database, link them and then create synonyms from one database to another only for the tables that the user can access via his queries.
The user will run his queries on the database you have just created and he will be limited to those tables that have synonyms on it.
I do not know if this would be the best option because your description of the case is relatively vague but based on the information I have this could be a solution.