SQLyog (webyog) change table access for root - sqlyog

We are more than 1 user working on SQLyog (webyog), we all use root to login, recently it has been brought to my attention that some confidential data has been leaked from 1 of the tables that I work on. I have been instructed to have a look into this. Can I protect this table with a new user account from root?

Change the root password immediately.
Your employer is liable for a couple incidents given your scenario.
If confidential info of any kind is being stored on that server, only the people with proper training and classification should have access to said information.
You should create a new user for EACH employee (or for each employee type [e.g: 'root', 'accounting', 'library', 'developer']) and give permissions accordingly.
The only user with global access should be root, and possibly whatever developer account you may create.
Everyone else should have access only to the tables they need and only have access to basic CRUD (Create, Update, Delete) functions. Your accountant may know basic SELECTing statements, but he shouldn't be DROPping tables.

Related

CouchDB simple document design: need feedback

I am in the process of designing document storage for CouchDB and would really appreciate some feedback. These documents are to represent "assets".
These databases will also be synced locally to the browser via pouchdb.
Requirements:
Each user can have many assets
Users can share assets with others by providing them with a URI such as (xyz.com/some_id). Once users click this URI, they are considered to have been "joined" and are now part of a group.
Group users can share assets of their own with other members of the group.
My design
Each user will have his/her own database to store assets - let's call it "user". Each user DB will be prefixed with the his/her unique ID.
Shared assets will be stored in a separate database - let's call it "group". shared assets are DUPLICATED here and have an additional field for userId (to indicate creator).
Group database is prefixed with a unique ID just like a user database is prefixed with one too.
The reason for storing group assets in a separate database is because when pouchdb runs locally, it only knows about the current user and his/her shared assets. It does not know about other users and will should not query these "other" users' databases.
Any input would be GREATLY appreciated.
Seems like a great design. Another alternative would be to just have one database per group ("role"), and then replicate from a user's group(s) into their local PouchDB.
That might get hairy, though, when it comes time to replicate back to the server, because you're going to have to filter the documents as they leave the user's local database, depending on which group-database they belong to. Still, you're going to have to do that on the server side anyway with your current design.
Either way is fine, honestly. The only downside of your current approach is that documents are duplicated on the server side (once per user-db and once per group-db). On the other hand, your client code becomes dead-simple, because you don't have to do any filtered replication. If you have enough space on your server not to worry about it, then I would definitely go with your approach. :)

Web user is not authorized to access a database despite having Editor access in the ACL

In my XPages application, web users can perform a self-registration. In the registration process, a user document for the web user is created in the address book and the user is added to a group that has Editor access for the database. After executing show nlcache reset on the Domino server, the user can login to and access the application.
In ~98% of all registrations this works perfectly fine. However, sometimes new users cannot enter the application after the login because, according to the Domino server, they "are not authorized to access" the database. The login must have worked because the user id is correct. The exact same user id can also be found in the Members field of the group that has Editor access to the database. To additionally verify the user's access level, I executed NotesDatabase.queryAccess() with the user's id. It returned 0, which is the ACL default and means "No Access". Yet, there are dozens of users in the same ACL group which have absolutely no problem with accessing the database.
At the moment, we "circumvent" this problem by manually removing the user's document from the address book as well as remove him/her from the Members of the ACL group. Afterwards we ask the user the re-do the self-registration with the exact same information as before. Up to now, this second registration has always worked and the user can access the application. Yet, this is not a real solution, which is why I have to ask if anyone knows what could be the problem?
Don't create entries in the address book directly. Use the adminp process for registration. To minimize perceived delay send a validation/confirmation message the user has to click.
Comment of 12/02/2015 seems to be the correct Answer:
Check if the self-registrated user has TWO consecutives spaces in his name, (could be because trailling space too)
In group domino do a FullTrim. So we have
John<space><space>Smith
that is not in group XXX because in the members it's:
John<space>Smith.
This may have something to do with the frequency at which the views index are refreshed in the names.nsf
Since the access control is done groups in the ACL, the server will "know" which user belongs to which group only after the views index have been updated.
In a normal setting, this can take a couple of minutes.
You can test this hypothesis by forcing an index refresh, either with CTRL-MAJ-F9 from your Notes client (warning, can take very long depending on network and number of entries in the names.nsf) or with the command
load updall -v names.nsf
... or by having the users wait a little while and try again 5min later.
Ok, first a question. If you let the user wait a couple of minutes will the access then work? I.e. is it a refresh/caching problem - or an inconsistency in the way you add the user to the group?
I assume that the format of the user name is correct as it works in most cases (i.e. fully hierarchical name)... Is there anything "special" about the names that do not work?
I do a similar thing (and has done several times) - although with some differences :-)
I typically use Directory Assistance to include my database with a "($Users)" view. When I update anything in this view I do a view.refresh() on the view (using Java). I typically do not use groups in these type of applications (either not applicable - or I use OU's or roles for specific users). I am not sure how the group membership is calculated - but I guess you could try to locate the relevant view (though none of them seemed obvious when I looked) - and do a refresh on it.
/John

Login system using physical postgres users not "logical" users

I'm currently building an application that has to conform with SOX auditing requirements. One of these, is that all inserts, updates and deletes (but delete you can ignore), need to leave a trail that is difficult, if not impossible for a standard user (or non-DBA) to change.
This means, I need to enforce the auditing at the database level via triggers on insert, update and delete.
My problem is; this is a webapp... The typical design pattern is to store users as "logical", for example; in a "users" table. What I need, is for the application to actually run as the logged in user after the initial login.
My thinking (which is likely not the best) is to do the following:
Load the login page via a standard username (webapp)
Check a table called "stored_users" for their logical username/password.
If they enter the correct user/pass; retrieve the db username, generate a session password (stored in KVSession on redis), update the user on the postgres DB and login with it.
After a defined time of inactivity, destroy the password session, reset the db password for the user and log them out.
Does this sound like a safe way to ensure the following?
My users are always using postgres users; so I can enforce the triggers via CURRENT_USER etc..
Security by always regenerating the postgres user password with a random, temporary password
I'd really like to hear what others have to say on this matter; as I really can't find this on Google (or I'm not searching the right terms). It seems the prevailing mindset for user logins is to store them as logical records and have a global connection user.
To achieve your goal
all inserts, updates and deletes, need to leave a trail that is
difficult, if not impossible for a standard user to change.
you can create:
1) Two schemas: one for common tables, one for security stuff like login/pass(hash) table, user session log, change log table, etc.
2) Two users: one common user, that can only use dml on common schema (no ddl), one superuser.
3) Login function that will check provided user/pass against login/pass table and log successful/failed attempts into user session log (you need SECURITY DEFINER function)
4) Set of audit triggers on common schema tables that will check the user privileges and log any changes, made by the user (SECURITY DEFINER functions here too).

CQRS when reading with permissions for large data set

I am trying to understand how the read side of CQRS can work with a large document management application (videos/pdf files/ etc) that we are writing.
We want to show a list of all documents which the user has edit permission on (i.e. show all the documents the user can edit).There could be 10,000s of documents that a particular user could edit.
In general I have read that the a single "table" (flat structure) should suffice for most screens and with permissions you could have a table per role.
How would I design my read model to allow me to quickly get the documents that I can edit for a specific user?
Currently I can see a table holding holding my documents, another holding the users and another table that links the "editing" role between the user and the documents. So I am doing joins to get the data for this screen.
Also, there could be roles for deleting, viewing etc.
Is this the correct way in this case?
JD
You can provide a flat table that has a user id along with the respective denormalized document information.
SELECT * FROM documents_editable_by_user WHERE UserId = #UserId
SELECT * FROM documents_deletable_by_user WHERE UserId = #UserId
SELECT * FROM documents_visible_for_user WHERE UserId = #UserId
But you could even dynamically create a table/list per user in your read model store. This becomes quite easy once you switch from a SQL-based read store to NoSQL (if you haven't already.)
Especially when there are tens of thousands of documents visible for or editable by a user, flattened tables can give a real performance boost compared to joins.
When I had a read model that took the form of a filtering-search-form (pun not intended), I used rhino-security as the foundation of an authorization service.
I configured the system so that the authorization service's tables got pushed through SQL Server's pub-sub system and SQL Server Agent, to the clients that were partially displaying the denormalized data - I then let Rhino.Security join the authorization model together into the read model, on a per-user basis.
Because I essentially never wrote to the read model's authorization tables from the read model, we got a nice encapsulation on the authorization service's database and logic, because authorization was only changed through that service, and it was globally unique and specific (consistent) to that service. This meant that our custom GUIs for handling advanced (hierarchial entities, user groups, users, permissions, per-entity-permissions) authorization requirements could still do CRUD against this authorization model and that would be pushed in soft real time to any read model.

Authorization System Design Question

I'm trying to come up with a good way to do authentication and authorization. Here is what I have. Comments are welcome and what I am hoping for.
I have php on a mac server.
I have Microsoft AD for user accounts.
I am using LDAP to query the AD when the user logs in to the Intranet.
My design question concerns what to do with that AD information. It was suggested by a co-worker to use a naming convention in the AD to avoid an intermediary database. For example, I have a webpage, personnel_payroll.php. I get the url and with the URL and the AD user query the AD for the group personnel_payroll. If the logged in user is in that group they are authorized to view the page. I would have to have a group for every page or at least user domain users for the generic authentication.
It gets more tricky with controls on a page. For example, say there is a button on a page or a grid, only managers can see this. I would need personnel_payroll_myButton as a group in my AD. If the user is in that group, they get the button. I could have many groups if a page had several different levels of authorizations.
Yes, my AD would be huge, but if I don't do this something else will, whether it is MySQL (or some other db), a text file, the httpd.conf, etc.
I would have a generic php funciton IsAuthorized for the various items that passes the url or control name and the authenticated user.
Is there something inherently wrong with using a naming convention for security like this and using the AD as that repository? I have to keep is somewhere. Why not AD?
Thank you for comments.
EDIT: Do you think this scheme would result in super slow pages because of the LDAP calls?
EDIT: I cannot be the first person to ever think of this. Any thoughts on this are appreciated.
EDIT: Thank you to everyone. I am sorry that I could not give you all more points for answering. I had to choose one.
I wonder if there might be a different way of expressing and storing the permissions that would work more cleanly and efficiently.
Most applications are divided into functional areas or roles, and permissions are assigned based on those [broad] areas, as opposed to per-page permissions. So for example, you might have permissions like:
UseApplication
CreateUser
ResetOtherUserPassword
ViewPayrollData
ModifyPayrollData
Or with roles, you could have:
ApplicationUser
ApplicationAdmin
PayrollAdmin
It is likely that the roles (and possibly the per-functionality permissions) may already map to data stored in Active Directory, such as existing AD Groups/Roles. And if it doesn't, it will still be a lot easier to maintain than per-page permissions. The permissions can be maintained as user groups (a user is either in a group, so has the permission, or isn't), or alternately as a custom attribute:
dn: cn=John Doe,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: webAppUser
cn: John Doe
givenName: John
...
myApplicationPermission: UseApplication
myApplicationPermission: ViewPayrollData
This has the advantage that the schema changes are minimal. If you use groups, AD (and every other LDAP server on the planet) already has that functionality, and if you use a custom attribute like this, only a single attribute (and presumably an objectClass, webAppUser in the above example) would need to be added.
Next, you need to decide how to use the data. One possibility would be to check the user's permissions (find out what groups they are in, or what permissions they have been granted) when they log in and store them on the webserver-side in their session. This has the problem that permissions changes only take effect at user-login time and not immediately. If you don't expect permissions to change very often (or while a user is concurrently using the system) this is probably a reasonable way to go. There are variations of this, such as reloading the user's permissions after a certain amount of time has elapsed.
Another possibility, but with more serious (negative) performance implications is to check permissions as needed. In this case you end up hitting the AD server more frequently, causing increased load (both on the web server and AD server), increased network traffic, and higher latency/request times. But you can be sure that the permissions are always up-to-date.
If you still think that it would be useful to have individual pages and buttons names as part of the permissions check, you could have a global "map" of page/button => permission, and do all of your permissions lookups through that. Something (completely un-tested, and mostly pseudocode):
$permMap = array(
"personnel_payroll" => "ViewPayroll",
"personnel_payroll_myButton" => "EditPayroll",
...
);
function check_permission($elementName) {
$permissionName = $permMap[$elementName];
return isUserInLdapGroup($user,$permissionName);
}
The idea of using AD for permissions isn't flawed unless your AD can't scale. If using a local database would be faster/more reliable/flexible, then use that.
Using the naming convention for finding the correct security roles is pretty fragile, though. You will inevitably run into situations where your natural mapping doesn't correspond to the real mapping. Silly things like you want the URL to be "finbiz", but its already in AD as "business-finance" - do you duplicate the group and keep them synchronized, or do you do the remapping within your application...? Sometimes its as simple as "FinBiz" vs "finbiz".
IMO, its best to avoid that sort of problem to begin with, e.g, use group "185" instead of "finbiz" or "business-finance", or some other key that you have more control over.
Regardless of how your getting your permissions, if end up having to cache it, you'll have to deal with stale cache data.
If you have to use ldap, it would make more sense to create a permissions ou (or whatever the AD equivalent of "schema" is) so that you can map arbitrary entities to those permissions. Cache that data, and you should ok.
Edit:
Part of the question seems to be to avoid an intermediary database - why not make the intermediary the primary? Sync the local permissions database to AD regularly (via a hook or polling), and you can avoid two important issues 1) fragile naming convention, 2) external datasource going down.
You will have very slow pages this way (it sounds to me like you'll be re-querying AD LDAP every time a user navigates to figure out what he can do), unless you implement caching of some kind, but then you may run into volatile permission issues (revoked/added permissions on AD while you didn't know about it).
I'd keep permissions and such separate and not use AD as the repository to manage your application specific authorization. Instead use a separate storage provider which will be much easier to maintain and extend as necessary.
Is there something inherently wrong with using a naming convention for security like
this and using the AD as that repository? I have to keep is somewhere. Why not AD?
Logically, using groups for authorization in LDAP/AD is just what it was designed for. An LDAP query of a specific user should be reasonably fast.
In practice, AD can be very unpredictable about how long data changes take to replicate between servers. If someday your app ends up in a big forest with domain controllers distributed all over the continent, you will really regret putting fine-grained data into there. Seriously, it can take an hour for that stuff to replicate for some customers I've worked with. Mysterious situations arise where things magically start working after servers are rebooted and the like.
It's fine to use a directory for 'myapp-users', 'managers', 'payroll' type groups. Try to avoid repeated and wasteful LDAP lookups.
If you were on Windows, one possibility is to create a little file on the local disk for each authorized item. This gives you 'securable objects'. Your app can then impersonate the user and try to open the file. This leverages MS's big investment over the years on optimizing this stuff. Maybe you can do this on the Mac somehow.
Also, check out Apache's mod_auth_ldap. It is said to support "Complex authorization policies can be implemented by representing the policy with LDAP filters."
I don't know what your app does that it doesn't use some kind of database for stuff. Good for you for not taking the easy way out! Here's where a flat text file with JSON can go a long way.
It seems what you're describing is an Access Control List (ACL) to accompany authentication, since you're going beyond 'groups' to specific actions within that group. To create an ACL without a database separate from your authentication means, I'd suggest taking a look at the Zend Framework for PHP, specifically the ACL module.
In your AD settings, assign users to groups (you mention "managers", you'd likely have "users", "administrators", possibly some department-specific groups, and a generic "public" if a user is not part of a group). The Zend ACL module allows you to define "resources" (correlating to page names in your example), and 'actions' within those resources. These are then saved in the session as an object that can be referred to to determine if a user has access. For example:
<?php
$acl = new Zend_Acl();
$acl->addRole(new Zend_Acl_Role('public'));
$acl->addRole(new Zend_Acl_Role('users'));
$acl->addRole(new Zend_Acl_Role('manager'), 'users');
$acl->add(new Zend_Acl_Resource('about')); // Public 'about us' page
$acl->add(new Zend_Acl_Resource('personnel_payroll')); // Payroll page from original post
$acl->allow('users', null, 'view'); // 'users' can view all pages
$acl->allow('public', 'about', 'view'); // 'public' can only view about page
$acl->allow('managers', 'personnel_payroll', 'edit'); // 'managers' can edit the personnel_payroll page, and can view it since they inherit permissions of the 'users' group
// Query the ACL:
echo $acl->isAllowed('public', 'personnel_payroll', 'view') ? "allowed" : "denied"; // denied
echo $acl->isAllowed('users', 'personnel_payroll', 'view') ? "allowed" : "denied"; // allowed
echo $acl->isAllowed('users', 'personnel_payroll', 'edit') ? "allowed" : "denied"; // denied
echo $acl->isAllowed('managers', 'personnel_payroll', 'edit') ? "allowed" : "denied"; // allowed
?>
The benefit to separating the ACL from the AD would be that as the code changes (and what "actions" are possible within the various areas), granting access to them is in the same location, rather than having to administrate the AD server to make the change. And you're using an existing (stable) framework so you don't have to reinvent the wheel with your own isAuthorized function.

Resources