I am working on a large Java EE web-app with CRM functionalit and we are looking for a security approach/library/solution/anything. Basic role-based security won't work since access control must be based on both role and hierarchy, but must be optionally customisable per document. Because there will be confidential and proprietary information stored, it is a requirement that the security works properly.
Example: To use department store, shelf stalkers stockers can create reports that other stockers can read only if they are in the same department. Now their department manager can read/write/update/delete all reports written by stockers and write reports that all others department managers can read but not see reports of store managers, etc, whom the district managers can r/w/u/d etc. Now, the complications: people at higher levels can make things visible to people at lower levels, either to individuals (department writes document to several specific stockers) users or everyone below them (store manager writes a memo to the entire store) or any permutation you can imagine. Also, individuals can create reports that their peers cannot see or they can choose grant access to store stockers in other districts etc.
We are considering an ACL with one permission per entity, but are worried about the large number of records that would create. Even if only a report was readable to everyone else in a department of 30 and every person above them [in the chain of command], creating a single report would require ~40 records! With 1 report per week per user that is 2000 permissions per user per year. 1,500 users means over 3,000,000 permissions per year.
It seems like a rule-engine based approach would be nice, but I have not seen any blogs or articles mentioning that approach so we're hesitant to that approach.
We are also considering some ACL/rule home-brew hybrid where you could grant permission to a department id with a discriminator of "manager" or "stockers" etc to subselect, but are worried that checking for all possible permissions (you could be granted permission specifically by another user, you have permission as a memeber of your department, you could have permission as a member of a store, or of district) sounds like an error-prone tedious nightmare.
What is the best approach for our application?
You could look at using Spring Security and ACL's - the nice thing about Springs ACL implementation is it is implemented with AoP it should be easier to integrate.
It sounds like your security requirements are quite complicated - off the top of my head I dont know how you'd implement this.. but you can reduce the number of records required by creating ACL's against your object hierarchy and having objects 'inherit' permissions from parent objects. You grant a user read permissions to the parent Department of a Report - so they would inherit read access to the child reports of that department. Alternatively a Manager might have read and update permissions on the Department. The key to all this is how your java object model has been structured.
I have had a similar situation in a system where there were thousands of articles in an object hierarchy of Business Unit -- Publication -- Issue -- Article. You can have hierarchys of ACL's - so in my system - users that had C/R/W permissions to a particular business unit, inherited permissions on all child objects in the hierarchy.
In my opinion Customization + Complexity = JBoss Drools, I don't have much experience using this technology but I believe it would be worth a look in your case, check out the latest drools samples at: http://blog.athico.com/2011/04/try-drools-example-in-less-than-minute.html
Related
I have seen videos and read the documentation of Cloud firestore, from Google Firebase service, but I can't figure this out coming from realtime database.
I have this web app in mind in which I want to store my providers from different category of products. I want perform a search query through all my products to find what providers I have for such product, and eventually access that provider info.
I am planning to use this structure for this purpose:
Providers ( Collection )
Provider 1 ( Document )
Name
City
Categories
Provider 2
Name
City
Products ( Collection )
Product 1 ( Document )
Name
Description
Category
Provider ID
Product 2
Name
Description
Category
Provider ID
So my question is, is this approach the right way to access the provider info once I get the product I want?
I know this is possible in the realtime database, using the provider ID I could search for that provider in the providers section, but with Firestore I am not sure if its possible or if this is right approach.
What is the correct way to structure this kind of data in Firestore?
You need to know that there is no "perfect", "the best" or "the correct" solution for structuring a Cloud Firestore database. The best and correct solution is the solution that fits your needs and makes your job easier. Bear also in mind that there is also no single "correct data structure" in the world of NoSQL databases. All data is modeled to allow the use-cases that your app requires. This means that what works for one app, may be insufficient for another app. So there is not a correct solution for everyone. An effective structure for a NoSQL type database is entirely dependent on how you intend to query it.
The way you are structuring your data looks good to me. In general, there are two ways in which you can achieve the same thing. The first one would be to keep a reference of the provider in the product object (as you already do) or to copy the entire provider object within the product document. This last technique is called denormalization and is a quite common practice when it comes to Firebase. So we often duplicate data in NoSQL databases, to suit queries that may not be possible otherwise. For a better understanding, I recommend you see this video, Denormalization is normal with the Firebase Database. It's for Firebase Realtime Database but the same principles apply to Cloud Firestore.
Also, when you are duplicating data, there is one thing that needs to keep in mind. In the same way, you are adding data, you need to maintain it. In other words, if you want to update/delete a provider object, you need to do it in every place that it exists.
You might wonder now, which technique is best. In a very general sense, the best way in which you can store references or duplicate data in a NoSQL database is completely dependent on your project's requirements.
So you should ask yourself some questions about the data you want to duplicate or simply keep it as references:
Is the static or will it change over time?
If it does, do you need to update every duplicated instance of the data so they all stay in sync? This is what I have also mentioned earlier.
When it comes to Firestore, are you optimizing for performance or cost?
If your duplicated data needs to change and stay in sync in the same time, then you might have a hard time in the future keeping all those duplicates up to date. This will also might imply you spend a lot of money keeping all those documents fresh, as it will require a read and write for each document for each change. In this case, holding only references will be the winning variant.
In this kind of approach, you write very little duplicated data (pretty much just the Provider ID). So that means that your code for writing this data is going to be quite simple and quite fast. But when reading the data, you will need to load the data from both collections, which means an extra database call. This typically isn't a big performance issue for reasonable numbers of documents, but definitely does require more code and more API calls.
If you need your queries to be very fast, you may want to prefer to duplicate more data so that the client only has to read one document per item queried, rather than multiple documents. But you may also be able to depend on local client caches makes this cheaper, depending on the data the client has to read.
In this approach, you duplicate all data for a provider for each product document. This means that the code to write this data is more complex, and you're definitely storing more data, one more provider object for each product document. And you'll need to figure out if and how to keep up to date on each document. But on the other hand, reading a product document now gives you all information about the provider document in one read.
This is a common consideration in NoSQL databases: you'll often have to consider write performance and disk storage vs. reading performance and scalability.
For your choice of whether or not to duplicate some data, it is highly dependent on your data and its characteristics. You will have to think that through on a case-by-case basis.
So in the end, remember that both are valid approaches, and neither of them is pertinently better than the other. It all depends on what your use-cases are and how comfortable you are with this new technique of duplicating data. Data duplication is the key to faster reads, not just in Cloud Firestore or Firebase Realtime Database but in general. Any time you add the same data to a different location, you're duplicating data in favor of faster read performance. Unfortunately in return, you have a more complex update and higher storage/memory usage. But you need to note that extra calls in Firebase real-time database, are not expensive, in Firestore are. How much duplication data versus extra database calls is optimal for you, depends on your needs and your willingness to let go of the "Single Point of Definition mindset", which can be called very subjective.
After finishing a few Firebase projects, I find that my reading code gets drastically simpler if I duplicate data. But of course, the writing code gets more complex at the same time. It's a trade-off between these two and your needs that determines the optimal solution for your app. Furthermore, to be even more precise you can also measure what is happening in your app using the existing tools and decide accordingly. I know that is not a concrete recommendation but that's software development. Everything is about measuring things.
Remember also, that some database structures are easier to be protected with some security rules. So try to find a schema that can be easily secured using Cloud Firestore Security Rules.
Please also take a look at my answer from this post where I have explained more about collections, maps and arrays in Firestore.
I'm trying to figure out what I need to specify in UML for a role-based access control system.
Basically I have a Database and only specific people are supposed to access specific functions or informations from that database. My academic helper told me to use a role-based access control system and scribbled some stuff onto a paper.
On the left you can see the 3 roles, and connected to it the database, both in the model part of the Model-View-Control.
My question basically: Which functions/variables do I need in the class Role and the role classes so the access control system works and why?
Generally this is supposed to be written in Java.
EDIT: Each Role has its own login credentials, so they will be identified upon login. With this login they are supposed to get one of those roles, but I don’t know how to give them that role.
I was looking for some diagram I found via google a long time ago, long before this question.
RBAC is a standardized model, it doesn't really contain multiple representations. You can extend it with additional security models, and it's multilevel, so higher levels are optional.
Flat RBAC, the first level, requires the following
users acquire permissions through roles
many to many user role assignment
many to many permission role assignment
user-role assignment review (user - role mapping can be changed, not hardcoded)
users can use permissions of multiple roles simultaneously
I have never seen a full implementation of RBAC in the wild. In a previous job we ultimately had to add point 2 to the application to enable administrators to go into a "support" mode, to view an accounts profile as they would.
This diagram gives a largely complete level 4 representation.
Here is the source of this diagram, it has a lot more information than what I'm saying.
I think the biggest variance you'll have (besides naming) is what object has "check access" and the general naming of these objects and methods.
For further reading on the subject, I would suggest these
Role-Based Access Control, Second Edition
ANSI blog
ANSI specification
NIST 4 levels of RBAC implementation
NIST adding attributes to role-based access control
Wikipedia RBAC, also contains UML
There are other documents including some criticisms, I usually find that simply using RBAC is not sufficient, as there are often more complex requirements than just "manager can do X", for example.
Well, still there are many, many ways to model this. And basically it's not an UML but a design issue. Anyway, here's a possibility:
A user has a single Role which is permanently assigned during a login. Of course a user with admin privilege could alter this role to something else. The Role holds a list of assigned Applications where the association class RoleApplication can hold attributes about what the role can do with the application.
Now how you control that an admin can change rights and all these pretty things that come along with a security system are definitely too broad to go here.
I am working on a project which is using micro-services architecture.
There is two services:
UserAPI : all thing related to user come here.
OMS : All things related to Order Come here.
I need to provide orders based on following filter :
By User Id
By Date
By Status
By User Phone Number
mix of above
So i create an API
path/orders?date=12/11/2016&status=delivered&phone=1111111111
Now i need to provide Orders for User by user ID. So which is good rest design:
Add user ID in query param in existing API like path/orders?user_id=1
Create a Separate API path user/{user_id}/orders
Both of your options are OK. But there are different semantics.
path/orders?user_id=1
This is looking up by orders. Orders maybe looked up for example to do some statistical analysis. The orders can be filtered by different parameters, the user id being one of them. For this (when the orders is the main interest) the above URI strategy is fine.
Now on the other hand you may want to look up a user and see their orders. Maybe to do some analysis on their ordering habits. Here you want user information along with their orders. This is where your second URI scheme would be better
user/{user_id}/orders
These are the orders that belong to the user. So it is a relationship. This is where this URI scheme works better.
So really there's nothing wrong with having both options. You just need to follow the semantics of when each should be used.
I have a problem that bothers me for quite some time, and I also came up with a solution, the question here is rather on how to best implement it, so I'm seeking advice from you if you've ever dealt with that situation before (it's hard to find anything useful on this topic on the web).
Situation
3-tier architecture (rich client such as Swing or Eclipse RCP or Android, web application with implementations of the service layer, relational database).
My models are POJOs (plain old Java objects, pure data containers with getters and setters), which are persisted (technical ID on all my models).
I'm often dealing with large models that are aggregatively used, but need to be efficiently read and transported. Let's say I've got following models:
User, with login name, password hash, salt, first/last name, e-mail address, authorization credentials, profile picture (Image)
Image, with name, content type and (usually large) data
Article, with text, and author (User)
Problem
Now when I'm listing or loading an article, I don't want to load the entire author (User), as it exposes too much details (password hash and salt) and carries too much data (credentials, image) for what I actually need in the context of an article (first/last name and e-mail).
Generally speaking: sometimes I need the full details of my models (when creating/editing them, or in very specific situations), but when I use them aggregatively in other models, I'd rather have a simplified form (if I need details, I could load them with a separate request).
Solution
For each model, I could create two variants: a full detail variant with full CRUD (create, read, update, delete) and a simplified, read-only variant, which can be used as a surrogate in aggregative relationships. The simplified model version also contains the technical ID of the detail version, so I could fetch that by demand.
For the User: the simplified model just has the first/last name and e-mail.
For the Image: the simplified model comes without the image data.
The article's author is the simplified version of the user, and the User's profile picture is the simplified version of the image.
Question
Is this an existing pattern? It somewhat relates to DTO (Data Transfer Object), but it's not the same. Has anybody seen this before?
Have you used something like this before? Any advice or tips on the naming, OO-relationship between the two representations?
I cannot correlate your solution option to a pattern that i am aware of. But your requirement(s) can be fulfilled by introducing a very thin API (Web API) on top of your service later.
There are two parts to it,
Reading: as you've mentioned, you may need to funnel specific selection of data items to the consumer based on the usage/permissions. This can be accommodated by specifying a set of facets in your incoming GET query.
Check here for a sample, https://developer.linkedin.com/documents/people-search-api
Writing: For fragments, use PATCH operations. This will give you the flexibility to update by field.
Check here for a sample: https://www.mnot.net/blog/2012/09/05/patch
All in all, what this gives you is a very flexible API with a very clean domain model under your API. And this is a widely accepted approach these days.
Hope that helps.
As the title says, i have a need to create a dynamic menu stored as a tree in the database and there are plans to put an interface on it.Now i need to decide how to implement the Access Control Layer based on what is on the market suitable for this requirement.
I heavily use Spring IoC, spring mvc etc....with hibernate for my project. I've used apache shiro before and it's not bad.just that the community is still young so it takes time for a question regarding shiro to have contributions and there is not extensive documentation.
I was still planing on using shiro anyway because i've an experience which i don't have with spring security.Now the first question should have been Is is a good idea to tie ACL to menu system|navigation system .I would be please if anyone could share his experience regarding that.
So on top of my head i have this model in mind users, roles, rights, users_rights ,roles_users, roles_rights
users //contains creds and user detail
roles //contains roles
rights // contains rights (including menu entries matching rights, if i have to tie them)
roles_users //many-to-many roles-users with extra columns mapped as entity
roles_rights // many-to-many roles-rights with extra columns mapped as entity
users_rights //many-to-many users-rights mapped as entity with extra columns. special rights for user and overwrite the overall rights given by roles. can deny rights given by a role or add rights not inside any roles
so in the rights table i could have like:
id
name // in the form of admin:users:list
description
menu_name // unique name what shows on page
menu_url
the only question is that how do i handle submenu? self many-to-many rights-rights?
at the end it all becomes so complex.So i would like have other perspective, insights ,suggestions. thanks
I hope I understood what you want.
I think that using a self foreign key is valid.
However, I would suggest that you compute the "ACL value" of a sub menu upon its creation, or upon update of one of the parents,
So you won't spent time calculating it while during ACL check for the sub menu.
I'm sorry if I didn't use the terms correctly,
What in general I mean is that if you have some value at a tree, and this value might be dependent on the value of the parent node in the tree,
you should consider to calculate the value for the child node/leaf during insertion , update, or any change at one of the ancestors.