How should hierarchical permissions be implemented efficiently in microservices? - microservices

I have a scenario where user permissions are scoped to a particular position in a hierarchy, e.g. a user may have permissions at a building, whereas another user only for a room inside that building. Resources can also be scoped at a particular position in the hierarchy.
I would like to allow for different entity types to define their own rules for whether a user can see a particular resource or not. E.g. a particular resource may be visible by anybody with permissions at or above the scope of the resource, whereas another may have a strict requirement that the user has to have the permission at exactly the scope of that resource.
The approaches I have thought of so far are:
Each microservice has a sidecar service which caches the hierarchy required for working out whether a particular resource is visible, but this then essentially requires the hierarchy to be located with all deployed microservices.
A single authorization service which is called to determine whether permission should be granted to perform an action for a particular resource.
Each microservice queries the hierarchy from the service which owns the hierarchy when needed, in order to retrieve the required information to determine the permission check itself.
Information around this particular style of permission in a microservice environment seems to be limited. What would be the recommended approach for such a situation?

I'd recommend approach 2, for the reason that your application will be unlikely to be the only consumer of the auth service as your architecture expands.
You would query the auth service whenever a user logs into any of your applications, and this would return a JWT with the permissions allocated to the particular user baked into it. Then when the user attempts to access the restricted resource, the Buildings service (or similar) would query the JWT to see if they have the appropriate permissions, and return the content that they have access to.

Related

Should I manually set user session when receiving messages?

I have resources that are protected per user. The user themselves are able to edit it, and then some super users are also able to edit it, but other users are not able to.
When it comes to endpoints, I have a user sessions and I can check their permissions to see if they are able to edit the resource or not.
However, when it comes to events/messages the service receives, there is no user sessions involved. So it is not able to edit those resources.
I know that the messages that we receive are safe (Only originate from our own systems), so I'm planning on manually setting the user session myself for all events/messages with a system user account.
I could also split the method to be something like updateResource and updateResourceNoPermissionCheck, but I'd rather not give the ability for anyone (including other developers) the ability to call the wrong method when they weren't supposed to.
Was wondering people's thoughts. Thanks in advance!
Yes, it's quite normal. I've seen cases when developers pass along the token via message headers, but I don't find it necessary. Providing enough user context information in the message contract establishes solid guarantees for the message receiver about who the user is. It is abnormal when your internal messaging system is exposed externally, which, of course, would create security risks as you cannot trust the sender.

How can Spring Security keep user A out of user B's data?

I know that Spring Security has a lot of role-based authorization capability. But what if I have two ordinary users accessing data. How do I keep User A from seeing records belonging to User B? For example, keeping User A from seeing the orders created by all other users?
Please note that this is NOT role-based authorization. User A and User B, etc., are all ordinary users, differing only in their identities.
In an existing Spring application I'm currently getting the job done with a filter in each DAO, ensuring that "... and user_id = $1 ..." is part of the queries. This also reduces the volume of fetched data, lowering database access costs.
In the future I will be breaking up my application into microservices. It seems to me that each microservice request must also have the UserDetails information. This sounds like an anti-pattern.
An API gateway would merely be a consumer of the approaches that I previously mentioned. So, is passing the UserDetails information to each microservice my best approach?
I hope the answer is not "create a role for each ordinary user, like "ROLE_USER_A", "ROLE_USER_B", etc.
Thanks,
Jerome.
In an existing Spring application I'm currently getting the job done
with a filter in each DAO, ensuring that "... and user_id = $1 ..." is
part of the queries. This also reduces the volume of fetched data,
lowering database access costs.
This is the correct approach
In the future I will be breaking up my application into microservices. It seems
to me that each microservice request must also have the UserDetails
information. This sounds like an anti-pattern.
There are several approaches you an use here. You could use spring security oauth, and separate the authentication server out into it's own component. Then the credentials will be stored in a central location. This will save you from having to pass the credentials around.
Another approach would be using perimeter security. Basically your gateway service would authenticate each request and then pass the user details to each component.
There are other approaches, but these two are pretty common.

Spring Security #PreAuthorize with application itself as user

I've got a spring application set up with spring security. I've got my service methods annotated with #PreAuthorize(...). So everyone from the web needs some specific rights to access those methods, which is fine.
But now I've got a new use case. There's a #Scheduled method running to do some checks and send messages. Currently only people with ROLE_USER are allowed to send messages. But now also the application itself has to send those messages.
How should I manage to have some kind of invisible user (= the application), which is logged in all the time and has specific rights? Or maybe "all rights" would be nice as well, so it just ignores all those security annotations.
Or maybe I don't need a "user" at all?
Thanks for your help!
EDIT: The main 2 questions are:
Should I create a real user for the application? Means: An entry in the user table of the database? How did you solve this? Maybe you do simply use the user account of the admin user (which is a real person)?
If I now have this "system" user. What's the best way to "use" it? For example I'd use #Autowired User systemUser to access this user wherever I need it. (Of course there's some point in the application config where I create a bean with this specific user).
EDIT2: Some more thoughts:
I think in the future I want to send messages from different subsystems of the application. So it's no choice to use the admin user, because I need a few different users with different names.
I was faced with similar problem and the solution I implemented was an internal and an "external" service implementation. The external one has the internal one autowired in. Any application-internal component, like your scheduled job, would have the internal service wired in. Any Web-exposed components would have the secured "external" service wired in, which would have the #PreAuthorize etc. annotations in place, but otherwise would act just as a delegate to the internal service.
I also log, before passing message onto the internal service, the principal of the authentication object which was used for authorization. You know you'll have one available in the SecurityContext, so pick it out and just make a note in your logs of someone external invoking internal services. I do the below (your principal could be non-username, but still, wanted to share):
final String currentUser = SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString();
I think that all the answers you provided are fairly common solutions, so it depends very much on your requirements. The app I'm working on has some intense audit requirements so we have a user set up for the application itself to use when it needs to invoke services through a scheduler. This allows us to log against a given principle. Perhaps you should clarify your requirements?

Looking for a way (preferably an API) to determine Effective Permissions on Active Directory object

We have a custom Active Directory integrated web app that helps users perform some self-service on their accounts (e.g. update photo, change phone number, reset password etc.) Our app runs on domain-joined servers, as Local System, and is thus able to authenticate to the AD using the server account(s).
We use a service connection point, that the app's clients use to locate an instance of our app. (Our app clients are hard-coded to look for certain keywords which are published on the servie connection point's keywords attribute.)
We recently had a situation wherein someone (we believe accidentally) changed the keywords on one of the service connection points resulting in an outage, since the clients could no longer find our SCP when querying the AD for our keyword(s).
The customer is a bit upset about this and wishes for us to provide them the ability to determine who can change the keywords on our SCPs. This feedback was passed on from our sales guys to us, and now we need to provide some way of helping them figure out who can change the keywords on our SCPs.
So, we're looking for an API to help us to determine Effective Permissions on our Active Directory service connection point objects, so we can alleviate this situation for the customer. We couldn't quite find an Effective Permissions / Access API that could help us list all the users who have effective write access to the keyword and other attributes on our SCPs.
Is there an API/other way that one can use to determine Effective Permissions on an Active Directory object?
It needs to be able to list all the users who have a specified access on a specified set of attributes of an Active Directory object.
This stack overflow post may be able to help you. LINQ to LDAP should also allow you to access the information pretty easily as well.

How to manage user/permissions in an environment web/PL/SQL correctly?

My team will develop an internal (known users) application that has an architecture based on Java as front-end and PL/SQL as back-end. So, currently we are thinking in a better solution to manage the user/permissions, and we have two options:
Each user has their own database account, granted with the permissions. Currently the legacy system use this approach and I don't like it because it manages permissions based on database objects' granularity. So, I believe it is a bad choice to have a database connection per user. Can you see more cons here?
Build some tables at database to store the users and theirs permissions/profiles and build a PL/SQL procedure to do the login, generating a token and include a parameter to all others PL/SQL to verify this token and then authorize (or not) the execution.
So, you can ask me: why not just manage your permissions in your web-application? Answer: Those PL/SQL are already done and are used by all legacy systems, and this web-application should behave according it (ie. User permissions should be managed by the PL/SQL and its granularity based in please.)
How do you proceed in this case?
I think using the database's built-in mechanism is always to be preferred over rolling our own. And that applies to logging in users as much as anything else.
The biggest single advantage of dedicated user accounts is that we can link a given session with a named user. Well, yes, duh. But the point is, doing thinks like auditing user activity or tracing a performance issue in some process is way more difficult in web applications with generic accounts.
To address your main objection, we don't have to manage database privileges at the user level. That's why we have roles. For normal users, a role will provide sufficient privileges.
So:
define a set of roles which match the various business jobs your application serves.
grant system and object permissions to those roles; remember that roles can be additive (i.e. we can grant privileges on a role to another role).
grant roles to the users.
Find out more.

Resources