Multi-tenant users / roles persistance not accepting same names in different domains - java

I have tried to use OACC framework
createResource("USER", "domain1","kim")
USER : resourceClass
domain1 : domain
kim : value to be stored (externalId)
Sorry if arguments order are mismatched
again I have called for :
createResource("USER", "domain2","kim")
in this case, the system conflicts to store the same name , logically yes, externalId can't be same.
But how can we store the real values into this, a normal Resource instantiate will result in its own ID.
Is there any api to "getRoles" if I pass in a UserName ?
A multi-tenant application will have (users/roles/permission) per domain, 1 user can exist in multiple domains !!

But how can we store the real values into this, a normal Resource instantiate will result in its own ID.
As you noticed, the createResource() method can accept a String externalId parameter, which has to be a globally unique string identifier for the new resource. "Globally unique" here means unique across all domains and resource classes.
The externalId is useful to reference OACC resources by an identifier from your application domain, without having to use or store the unique resourceId OACC generates and returns from createResource().
One way to use non-unique application domain identifiers as external IDs would be to prefix identifiers with an appropriate classifier to make them unique within OACC. Such a prefix could simply be composed of the resource class, domain, or both. To use your example:
createResource("USER", "domain1", "user.domain1.kim");
createResource("USER", "domain2", "user.domain2.kim");
Is there any api to "getRoles" if I pass in a UserName ?
In OACC you can model role assignment by having one resource "inherit" all permissions from another resource by granting it the *INHERIT permission. In other words, there is no explicit concept of roles within OACC and hence no dedicated method to "getRoles".
In any case, the best practice for authorizations is to check against permissions, not against role membership.
For auditing or administrative purposes, if you do need to find the resources a specific user inherits permissions from, OACC provides query methods such as getResourcesByResourcePermissions(). If, for example, all your "roles" were modeled as resources of the resource class ROLE, you could find the ones your user inherits with the following call:
getResourcesByResourcePermissions(userResource,
"ROLE",
ResourcePermissions
.getInstance(ResourcePermissions.INHERIT));

Related

Better way to secure REST resources in Spring?

I have a RESTful service that exposes resources like /user/{id}
Now, the user can provide the credentials, get the token and access the resource. However, once authenticated, the user can access the resources for any id.
Meaning, user1 can access the URIs like /user/1 as well as user/2 and so on. I ended up using a Principal in the controller methods and started checking the id of the Principal with the id the user is trying to access.
Further, the user has multiple resources associated with it. Say, user1 owns res1 and res2, user2 owns res3 and res4. These can be accessed via /user/1/res/2. I need a way where I can prevent /user/1/res/3 as res3 is owned by user1 and not user2.
But I believe that this problem is very common and I am not really convinced with my solution.
Is there a better way to deal with this problem?
Thanks
You should not be exposing resourse /user/{id} at all if you all user can do is access only their own ID.
If I understand correctly, just exposing /user is enough, find ID of user from Principal or session etc and return result.
If you really want to do it, you can have custom implementation of #PreAuthorize. Got this code from a blog.
#PreAuthorize("isUsersRes(#id)")
#RequestMapping(method = RequestMethod.GET, value = "/users/{id}")
public UsersfindById(#PathVariable long id) {
return Users.findOne(id);
}
public class CustomMethodSecurityExpressionRoot
extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {
public CustomMethodSecurityExpressionRoot(Authentication authentication) {
super(authentication);
}
And implemenation of isUsersRes
public class CustomMethodSecurityExpressionRoot
extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {
public boolean isMember(Long OrganizationId) {
//user logic
}
Check complete blog here
This is a common problem with varied solutions. Also its not a problem related to REST alone. We have had this ever since apps exist. Employee can see his salary slip, leave records, etc but not another employee's.
One solution I like the most is 'security in depth'. This idea comes from how I have seen this work in banking systems for decades. This needs to get supported in the DB layer first.
You would need a table design like this example (or whatever your app's entity hierarchical structure is):
Organisation
-Dept
--user
And all non-master tables need to have a relation to one of these entities. Example:
Payslip -> user
Leave record -> user
Manager -> dept
HR Manager -> org
etc...
You would need another table to map out the basic access levels (This can get complex if we need to implement different sub access levels)
user1:dept2:org1
user2:dept2:org1
(I have seen some implementations that send this table's info as part of an encrypted access token that is used on every access request if the access has to be sessionless.)
You have not mentioned a framework/language but most languages have a database layer. For example if the DB layer is hibernate-java. There are interceptors (https://docs.jboss.org/hibernate/core/3.6/javadocs/org/hibernate/Interceptor.html#onPrepareStatement(java.lang.String)) that can be used to modify the query thats being executed.
Every query to DB will go with additional where-clause for these relationship keys.
We can get clever with Spring AOP, REST interceptors and a lot of other techniques on top of this basic architecture to enforce this security.
Idea will be that DB layer does not return data thats not accessible to the logged in user principal irrespective of what queries higher layer code uses.
if this is in place, a REST GET call for
/payslip/user1/Jan-2017
will end up with a 404 and not a 403.
Expecting this to be solved by a framework or a superficial set of interceptors is both risky and not future proof. We end up continuously tweaking the interceptors as the url patterns evolve.
Addition to show table examples:
ACL table
user, uid, dept, org
--------------------
jhon, 1 , 1 , 1
mary, 2 , 2 , 1
will, 3 , 2 , 1
Payslip table
--------------
month, net, deductions,..., uid
-------------------------------------
Jan , 200, 15.5 ,..., 3
Feb , 200, 15.5 ,..., 3
Project table
-------------
pname, pstart, pbudget, dept
------------------------------------
mark1, 12/21 , 20000 , 2
markx, 12/31 , 40000 , 2
What you want is user roles and permissions + cross user control. To find out user roles and permissions refer this
Also additionally you may want to cross check their user ID to the resource ID. Since you cannot let user1's resource ID 1 to view by user2, you will need to add userID as part of the resource id ex:- /user/user_id_1.
Otherwise we don't have a logical way to separate which resources are applicable to which users.

ACL Principal vs GrantedAuthority Concepts

I'm reading about Spring Security ACL lib and I am a bit confused about some concepts. Regarding SIDs, it states to my confusion:
ACL_SID allows us to uniquely identify any principal or authority in
the system ("SID" stands for "security identity"). The only columns
are the ID, a textual representation of the SID, and a flag to
indicate whether the textual representation refers to a prncipal name
or a GrantedAuthority.
So is principal the same as role? Is GrantedAuthority an equal concept or a particular role? Does a boolean field principal = true mean that the identifier has semantical value or simply that it is a role within the system?. If so, why do you want to store SIDs that are not accounted in the system?
An ACL (Access Control List) consists of a number of entries (rules), where every entry references a sid, which is a user or a group of users to apply the entry/rule for.
If the principal field is set to true, the sid is a principal, that is a single user. The sid field then contains the username.
If the principal field is set to false, the sid is an authority, for example ROLE_ADMIN. A GrantedAuthority is basically the same as a role (a role is a kind of authority).

How can I delete a group from LDAP using java?

someone knows how can I delete a group from LDAP using java? and how is the best way to verify is this group is empty?
Thanks,
LDAP operations maps to JNDI api. According to the specification available here: http://docs.oracle.com/javase/tutorial/jndi/ldap/operations.html, you can use following method:
void destroySubcontext(String name) throws NamingException
Which should destroy the named context and remove it from the namespace.
Quote from the documentation below:
"This method is idempotent. It succeeds even if the terminal atomic name is not bound in the target context, but throws NameNotFoundException if any of the intermediate contexts do not exist.
In a federated naming system, a context from one naming system may be bound to a name in another. One can subsequently look up and perform operations on the foreign context using a composite name. However, an attempt destroy the context using this composite name will fail with NotContextException, because the foreign context is not a "subcontext" of the context in which it is bound. Instead, use unbind() to remove the binding of the foreign context. Destroying the foreign context requires that the destroySubcontext() be performed on a context from the foreign context's "native" naming system.
Parameters:
name - the name of the context to be destroyed; may not be empty"
Use the UnboundID LDAP SDK to establish a connection to the server, then create a delete request specifying the DN of the group to delete. Transmit the delete request to the server and interpret the response.
DeleteRequest deleteRequest =
new DeleteRequest("cn=entry to delete,dc=example,dc=com");
try
{
LDAPResult deleteResult = connection.delete(deleteRequest);
System.out.println("The entry was successfully deleted.");
}
catch (LDAPException le)
{
System.err.println("The delete operation failed.");
}
If the LDAP client wishes to "empty" the group, which I take to mean "delete all attributes in the entry, LDIF can be constructed to remove all values of an attribute:
##
## assume 'member' is the attribute that whose values are members:
##
dn: cn=group1,ou=group,dc=example,dc=com
changetype: modify
replace: member
'Replace' with no value deletes all values of the member attribute whether any values exist or not. 'Delete' with no value deletes all values, but there must be at least one to delete.
Generally speaking, if there is choice, the UnboundID LDAP SDK should used instead of JNDI.
see also
LDAP: Mastering Search Filters
LDAP: Search best practices
LDAP: Programming practices

Java – efficient, database-aware instance-level authorization?

In a JPA app I have a scenario in which the app is to
list all accounts the given user is authorized to withdraw from
I have the Account entity and a many-to-many table that lists what authorizations each user has on each account – to implement the above scenario, the app currently just inner-joins the two tables – which is quite quick.
Now, I was planning to add an explicit authorization layer (based on apache shiro / spring security / other) to insulate authorization-related logic from the rest of the code, but...
There are some 10k Accounts in the database and the "average" user is granted "deposit" on all of them, "view" on one half of them and "withraw" on just a few.
Does any security framework allow to implement this scenario efficiently?
Ie: is any of them able to "decorate" a JPA query of the type "select a from Account a" (or the equivalent SQL) and thus get the list of accounts without loading all user grants from the database, and by all means, without having to retrieve all accounts?)
Have a look at Apache Shiro.
It allows you to pull in the User authorization once and cache it for the duration of the session. In addition, if all users can VIEW all ACCOUNTS then you wouldn't need to explicitly define this which would significantly reduce the overhead.
If your solution requires realtime access handlers Shiro has a way to reset the Permissions dynamically during runtime too.
Shiro allows you to implement a typical RBAC and define permissions like this:
domain:action:instance
So in your case permissions might look like this for a user:
account:deposit:* // deposit all accounts
account:view:1111
account:view:2222
account:view:3333 // view on these accounts
account:withdraw:5555
account:withdraw:6666 // withdraw on these accounts
In code you can then do something like this:
if (SecurityUtils.getSubject().isPermitted("account:withdraw:"+account.getAccountNumber() ) {
// handle withdraw
}
Shiro also has annotation driven permissions for additional abstraction.
EDIT
The Shiro permissions is the end result, not where you start. I used a set of tables representing mappings of the user-to-role and role-to-permission along with other mappings to instance. After AuthN its usually a simple set of queries indexed by the User PK to build up the data structures needed to render the permissions.
I have a hope that this is one of the possibilities to implement your requirement with Spring-Security.
Write custom org.springframework.security.acls.Permission like
ViewAccount,DepositToAccount,WithDrawFromAccount
Write custom
org.springframework.security.access.PermissionEvaluator Override
hasPermission(Authentication userAuthentication,Object
accountObject,Object oneOfThePermission) to check if the user has
the defined permission on the accountObject
Get reference to JPA
EntityManager in your custom evaluator and cross check/verify in DB
with user_id,permission_id,account_id
If the user is 'root' you can
staight away return true for hasPermission without verifying with
DB.
Annotate your service calls with
#PreAuthorize("isAuthenticated() and hasPermission(#accountArgument,
'respectivePermission')")
Refer link for custom implementations of Permission & PermissionEvaluator
If you are using EclipseLink there are a few features for this,
one is the #AdditionalCriteria annotation that allow a filter to be applied to all queries for a class,
http://www.eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_additionalcriteria.htm#additionalcriteria
another is EclipseLink's support for Oracle VPD (row level security in the database),
http://wiki.eclipse.org/EclipseLink/Examples/JPA/Auditing
and finally EclipseLink supports SessionEvents that can allow filter to be appended to any query execution,
http://www.eclipse.org/eclipselink/api/2.4/org/eclipse/persistence/sessions/SessionEventAdapter.html#preExecuteQuery%28org.eclipse.persistence.sessions.SessionEvent%29

to which resource class should this http get request be forwarded to?

Restlet's concept relies on using a unique URI for every resource, and every resource has its own resource class that defines the needed functions ( get,set, put, .. etc).
lets say in the database I have three tables,
companies
departments
employees
in this case, I have the following resources :
company
companies
department
departments
employee
employees
In case the client wants to find the name of employees in department X in the companies that are in city Y , what I want to say that, here the HTTP get request should be forwarded to which URI of the six available ones ? this HTTP get request is not associated with only one resource (table) but with multiple ones at the same time. How could this be configured ?
I hope you were able to catch my question.
edit :
in other words, in which resource class should the function or method that accesses the three tables in the database be placed ?
In my opinion employees b/c you need employees names. You can also return all employee info. The REST call should should go to output related entities.

Categories