What goes into Spring Security's ACL_OBJECT_IDENTITY table? - java

I'm attempting to integrate Spring Security with ACL support into an existing GWT application, and if I click another unhelpful link I swear will need a new mouse and keyboard. I've worked through what will be needed to use Spring to authenticate against Active Directory via LDAP, and I've worked out how we can assign custom permissions based on AD attributes (i.e. group membership), and I've even worked out how to perform a custom check against permissions (a true bitmask operation) using a custom ACL schema. What I haven't figured out is just what goes into the ACL tables.
ACL_SID
id:bigint (pk)
principal:boolean (ak)
sid:varchar (ak)
This table is pretty self-explanatory; we'll be using non-principal entries here only.
ACL_CLASS
id:bigint (pk)
class:varchar (ak)
This table is also pretty self-explanatory. As I understand it, we simply create an entry for every class/interface we wish to secure.
ACL_ENTRY
id:bigint (pk)
acl_object_identity:bigint (fak)
ace_order:int (ak)
sid:bigint (fk)
mask:bigint
granting:boolean
audit_success:boolean
audit_failure:boolean
This table is also mostly self-explanatory; we've customized the schema with a bigint/long in the mask field, but the question stems from just what acl_object_identity is referencing. Obviously, it points to the field in ACL_OBJECT_IDENTITY, but...
ACL_OBJECT_IDENTITY
id:bigint (pk)
object_id_class:bigint (fak)
object_id_identity:bigint (ak)
parent_object_identity:bigint (fk)
owner_sid:bigint (fk)
entries_inheriting:boolean
The object_id_identity is, what? A method? How is it referenced by way of Spring Security's annotations?
MyClass.java
#PreAuthorize("hasPermission(#someInput, 'READ')")
public boolean myMethod(String someInput) {
return true;
}
Presumably, #someInput refers somehow to the ACL_OBJECT_IDENTITY.object_id_identity field, but how?

First you need some kind of domain object class to store your data. This class must have a getId() method. For example:
public class DomainObject {
private Long id;
private String data;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
Change your secured method to:
#PreAuthorize("hasPermission(#someInput, 'READ')")
public boolean myMethod(DomainObject someInput) {
return true;
}
Now, someInput.getId() is the same as ACL_OBJECT_IDENTITY.object_id_identity.

have a look at the Grails Spring Security ACL Plugin Documentation.
It explains the domain classes used for the specific plugin, but it might help you. Look for AclObjectIdentity and AbstractAclObjectIdentity.
The ACL_OBJECT_IDENTITY.object_id_identity field is the instance id and uniquely identify the instance (together with object_id_class)
In your example, 'someInput' would be that instance.
this piece of code is taken from the beforementioned documentation:
#PreAuthorize("hasPermission(#report, delete) or hasPermission(#report, admin)")
void deleteReport(Report report) {
report.delete()
}
It explains itself immo. The report is deleted if the currently authenticated user has permission 'admin' or 'delete' for the given Report instance. Report is someInput in your code snippet.
Hope this helps.

The question seems to suggest a slight misunderstanding of Spring ACL. In the question, we are asked how to register an ACL for a String object, so that this method protection will work:
#PreAuthorize("hasPermission(#someInput, 'READ')")
public boolean myMethod(String someInput) {
return true;
}
As mentioned in this answer, it doesn't really make sense to protect a String object. When you think about it, this makes sense. Loosely speaking, we can divide all objects into two categories:
Objects that are persisted to the DB - let's call them entities
Objects that are not persisted to the DB - let's call them transients
In any real-life use case I can think of, it only makes sense to protect access to an entity, not a transient; I'll argue for this case in general later. To start with though, let's stick with a use case related to that of the question to see why protection of a transient probably isn't what's desired in this case.
Use Case
It's not 100% clear what the use case is in the question e.g. what someInput represents. But I'm assuming the use case is similar to the following. Suppose there are BankAccount entities and some operation on those entities e.g. readAccount. Only users who have read access to a BankAccount should be allowed to call readAccount. Now, BankAccount entities may be uniquely identifiable by their accountNumber, which is of type String. So we may be mistakenly led to try something like this, which is similar to the code in the question:
#PreAuthorize("hasPermission(#accountNumber, 'READ')")
public Account readAccount(String accountNumber) {
//CODE THAT RETRIEVES THE ENTITY FROM THE DB AND RETURNS IT
}
OK, it's not a bad assumption to make. I suppose the idea in our minds at this stage is that Spring ACL stores a table of account numbers, and for each account number, a list of people who have READ access to it. The problem is, Spring ACL doesn't work like that. As mentioned in this answer, Spring ACL identifies an objects in the following way:
What is the class of the object? In this case, it would be java.lang.String
What is the ID of the object? In this case, Spring ACL requires that the object needs a getId() method. Luckily, if you're using Hibernate, all your entities will have this by default, so you don't need to do anything extra to implement it. But what about String? Well, this doesn't have a getId() method. So Spring ACL won't be able to register an ACL for it and you won't be able to set up any permissions for Strings.
When you think about it, it actually makes sense that Spring ACL is designed this way. The getId() method allows us to associate the persisted ACL permissions entries with the persisted entities. This is the typical use case. So in the above example, what we're really trying to do is restrict access to Account objects, not account numbers. In that case, we have two options: preauthorize or postuathorize.
With pre-authorize, we'd need the fully-qualified path to the Account class. So let's say it's in the package X.Y, we'd have:
#PreAuthorize("hasPermission(#accountId, 'X.Y.Account', 'READ')")
public Account readAccount(Long accountId) {
//CODE THAT RETRIEVES THE ENTITY FROM THE DB AND RETURNS IT
}
Notice that in the above, we are using the ID, not the account number, to identify the account. This is the only way you are allowed identify an entity with Spring ACL, because the getId() is the link between the ACLs and their associated objects. Of course, you're free to write whatever code you like to retrieve the object by the given ID e.g. you could do something silly like increment the ID before retrieving it. So the object returned isn't guaranteed to be the same one that's authorized in this case: that's up to you to write the correct retrieval code.
The other way we can protect the method is with post authorize, as follows:
#PostAuthorize("hasPermission(returnObject, 'READ')")
public Account readAccount(String accountNumber) {
//CODE THAT RETRIEVES THE ENTITY FROM THE DB AND RETURNS IT
}
In this case, the code that retrieves the account entity is actually called, and then only after it's retrieved, the account, which is the object returned, is checked by the ACL framework against the current user and the READ permission. An advantage here is that we can retrieve the account any way we like e.g. by accountNumber in this case. Another advantage is that the object that's authorized is guaranteed to be the same as the one returned. The disadvantage is that we have to actually do the retrieval before we can make the call as to whether the user has permission or not. And if they don't have permission, then the retrieved object is effectively thrown away and so it may be a bit less performant than #PreAuthorize if the retrieval code is expensive to run.
Why Protecting Strings with Spring ACL Doesn't Make Sense Anyway
Technically speaking, I suppose you might be able to protect Strings, or indeed any other transient as long as it has a getId() method. With Strings, we could maybe add an extension function getId() for example. But I can't think of a practical use case for why we'd want to do that. For example, imagine we not only have Account objects but we also have Customer objects. And let's say Customer objects are uniquely identifiable by a customerNumber field, which is a String. And suppose we want to restrict access to customers in a similar way to accounts. Then what if coincidentally a customerNumber matched an accountNumber? In Spring ACL, we are only allowed one entry in the object identity table for every combination of object class plus ID, as per the Spring docs:
CONSTRAINT uk_acl_object_identity UNIQUE (object_id_class, object_id_identity)
So, suppose the String "fadfads389" happens to be both a customerNumber for some Customer and an accountNumber for some Account. If we were to restrict access to it via Spring ACL, what would that mean? Would it mean that a user has access to the account? The customer? Both?
Hopefully this example demonstrates why it doesn't really make sense to protect some transient class such as String with Spring ACL when that transient is used to identify entities: when we're interested in protecting entities we just protect the entities themselves, using the implicit ID of those entities e.g. the ID stored by Hibernate.
Transients Could Still be protected
Of course, there's nothing stopping you from adding object identity entries into the Spring ACL acl_object_identity table for any class you want, as long as that class has a getId() method. So it is certainly possible for you to add permissions relating to transients, and should those transients appear again in memory then Spring ACL will kick in. But this isn't really what Spring ACL was designed for - it's really meant to protect entities, not transients, which are linked to the ACL logic by getId().
Strings Could Still be Used in PreAuthorize
Now, although we shouldn't really use Spring ACL to protect Strings, that's not to say that #PreAuthorize is completely off the table when it comes to Strings. We note that #PreAuthorize can handle any SpEL expression, the same for #PostAuthorize and the other method annotations as pointed out here. So, for example, you would be able to do something like this:
#PreAuthorize("#user.accountNumbers.contains(#accountNumber)")
public Account readAccount(String accountNumber, User user) {
//CODE THAT RETRIEVES THE ENTITY FROM THE DB AND RETURNS IT
}
The above assumes that the User class maintains a list of account numbers to which that user has access, so presumably a User is an entity, or at least is backed by some DB-persisted data.
However, beware if you do want to go down this path. Not only do you risk entangling your access control logic with the rest of your business logic, you also might lose out on the performance front; Spring ACL uses caching to make permissions lookups fast whereas the above code presumably needs to fetch User data from the DB in order to do the authorization.

Related

Entity to DTO conversion increases security

I have a question to ask regarding conversion of an Entity to DTO. I have read that it is good to convert the Entity to DTO in rest application so that it hides your entity data.
For e.g
If i have an entity User and there are two rest endpoints - GET and PUT. GET fetches the data and PUT updates the data. Now if i do not convert the Entity into DTO i would expose my Entity instances and someone could use the instance with PUT method and update the User Data.
But my question is this thing can also happen if i am using the same DTO class to convert the data while using the GET and PUT method (which most developers do). So how does conversion of entity to DTO increase security.
User.java
#Entity
#Table
public class User{
private int id;
private int name;
private String password;
}
Please give you valuable comments to clarify this doubt of mine. Thanks!
You explicitly define which attributes are available to your application's peripherals. I'm not sure this increases security, but it protects you from unwanted behavior. If you automatically convert your REST bodies to JSON via Jackson, every getter of your entity would be exposed. Hence if you add a getXXX method to evaluate something in your domain, you could unwillingly expose this to the outside world.
For instance you might not want to expose which authorizations are available for your user, or the user's password.
I like to use the Adapter Pattern for REST/JMS interaction.
Separation of concerns.
GET: In your example you would not return id back to the client would you?
PUT: You would not populate the id.

JPA setting referenced property without retrieving it. Best practices

Let's assume I have Entity that have nested Entity inside it.
For example (please, ignore missing annotations, getters/setters, etc):
#Entity
class User {
private String userId;
private Set<UserOperation> userOperations;
}
#Entity
class UserOperation {
private String someString;
// This is nested referenced entity
private User user;
}
Let's assume that I want to insert new UserOperation and all that I have is userId.
Can I do something like:
// We just create new user. There is no interaction to get existing from DB. Totally only 1 insert
User user = new User();
user.setId("someId")
UserOperation uOp = new UserOperation();
uOp.setUser(user);
uOp.setSomeString("just op");
em.persist(uOp);
Or I should go that way only:
// We retrieve existing user. There is interaction to get it from DB. Totally 1 select and 1 insert
User user = em.find("someId")
UserOperation uOp = new UserOperation();
uOp.setUser(user);
uOp.setSomeString("just op");
em.persist(uOp);
What is the right way of doing it?
Because from DB perspective userOperation table just have String user reference, so ID should be enough. Java requires an object.
When call "new User" I would like to avoid, properties of existing user be flushed (as they are all not set) or JPA trying to insert new user and operation failing due to primary key violation.
Some examples are welcomed.
For your use case, there is particularly method getReference() in EntityManager. It gives you an entity object for id, but does not access DB to create it. Therefore the best solution is a slightly modified 2nd solution of yours:
// We retrieve a stub user for given id. There is no interaction with DB
User user = em.getReference("someId", User.class);
UserOperation uOp = new UserOperation();
uOp.setUser(user);
uOp.setSomeString("just op");
em.persist(uOp);
Explanation:
getReference() has the same logical meaning as find(), with the exception that it does call DB. The consequence is that it does not check if there is a row in DB table with the given id, and that the object you get does not yet contain the data. However, the object is fully capable to load additinal data when get method is called. Therefore the object is fully usable even if retrieved by getReference() - in fact it works the same way as lazy loading.
A side note to your first solution:
The first solution would not work, as it would create a new entity user and then it would fail either when storing the entity to DB if it is cascaded (persist always calls insert and it would try to insert user with the same ID as exists in DB), or it would fail that UserOperation is to be persisted while user is not. In order to fix this solution, you would need to call em.merge(user) before you call em.persist(userOperation). But again, this would call a select to DB in the same way as em.find().
The best way to do this is using the second example. We should always try to use the actual object direct from db. Working with only the db reference will be way worse to mantain.
Now speaking specifically about Hibernate, it makes even more sense to work with whole objects, especially because of Hibernate's cascade, that can and will (if cascade is set) update the child entities of the one you are persisting to database.
Well, I have to admit that always fetching objects from database may cause some performance issues especially after the database gets a huge amount of data, so it's always important to implement nice and coherent model entities, and also keep in track of database hits from your application, and try to keep it the less possible queries being generated.
As for example, your own example (the second) is clean and easy to understand, I would stick with this approach, since it's really simple.
Hope it can solve your questons :)

Data Source Patterns - Where's to put table's level methods?

At my company we work with models based on "Active Record Pattern", the model methods are always related to operations of a single record from the database, for example:
Class User {
int id;
string Name;
public boolean Find (id); // SQL / ORM to return the object based on the user's Id;
public boolean Save (); // SQL / ORM to save / update a user
public boolean Delete (); // SQL / ORM to delete a user.
}
// Create the user "John"
Set objUser = new User ();
objUser.Name = "John";
objUser.Save ();
My question is that in relation to the database entity "User", we have methods that are to table level and not record, such as a method "getAllActiveUsers", which returns me a query object of all active users.
This type of situation ends up in own ActiveRecord model, which in my opinion does not make sense .. Could you help me to understand what would be the most advisable / elegant to treat this type of situation?
I read something about Gateway and Repository Patterns that may be useful for this, but was wondering if anyone has this same trouble and how did you solve ..
Thank you!!
I'm not a big fan of the Active Record Pattern but I think a consistent way of using it would be to add the getAllActiveUsers to the User class:
User.getAllActiveUsers();
On the other hand I would reccommend to use the Repository Pattern in the following cases:
You want to take advantage of Unit Testing.
You access the data source from many locations and you want to abract complexity.
You want a centralized place to handle caching.
You want a clear separation of concerns.
You want to apply a domain model so to simplify complex business logic.

Object Relational mapping and performance

I am currently working on a product that works with Hibernate (HQL) and another one that works with JPQL. As much as I like the concept of the mapping from a relational structure (database) to an object (Java class), I am not convinced of the performance.
EXAMPLE:
Java:
public class Person{
private String name;
private int age;
private char sex;
private List<Person> children;
//...
}
I want to get attribute age of a certain Person. A person with 10 children (he has been very busy). With Hibernate or JPQL you would retrieve the person as an object.
HQL:
SELECT p
FROM my.package.Person as p
WHERE p.name = 'Hazaart'
Not only will I be retrieving the other attributes of the person that I don't need, it will also retrieve all the children of that person and their attributes. And they might have children as well and so on... This would mean more tables would be accessed on database level than needed.
Conclusion:
I understand the advantages of Object Relational Mapping. However it would seem that in a lot of cases you will not need every attribute of a certain object. Especially in a complex system. It would seem like the advantages do not nearly justify the performance loss. I've always learned performance should be the main concern.
Can anyone please share their opinion? Maybe I am looking at it the wrong way, maybe I am using it the wrong way...
I'm not familiar with JPQL, but if you set up Hiernate correctly, it will not automatically fetch the children. Instead it will return a proxy list, which will fetch the missing data transparently if it is accessed.
This will also work with simple references to other persistent objects. Hibernate will create a proxy object, containing only the ID, and load the actual data only if it is accessed. ("lazy loading")
This of couse has some limitations (like persistent class hierarchies), but overall works pretty good.
BTW, you should use List<Person> to reference the children. I'm not sure that Hibernate can use a proxy List if you specify a specific implementation.
Update:
In the example above, Hibernate will load the attributes name, age and sex, and will create a List<Person> proxy object that initially contains no data.
Once the application accesses calls any method of the List that requires knowledge of the data, like childen.size() or iterates over the list, the proxy will call Hibernate to read the children objects and populate the List. The cildren objects, being instances of Person, will also contain a proxy List<Person> of their children.
There are some optimizations hibernate might perform in the background, like loading the children for other Person objects at the same time that might be in this session, since it is querying the database anyways. But whether this is done, and to what extend, is configurable per attribute.
You can also tell hibernate to never use lazy-loading for certain references or classes, if you are sure you'll need them later, or if you continue to use the persistent oject once the session is closed.
Be aware that lazy loading will of course fail if the session is no longer active. If for example you load a Person oject, don't access the children List, and close the session, a call to children.size() for example will fail.
IIRC the hibernate session class has method to populate all not-yet-loaded references in a persistent oject, if needed.
Best read the hibernate documentation on how to configure all this.

Correct way of finding what was modified by a post in an spring-mvc controller?

It is a rather general question, but I will give a stripped down example. Say I have a Web CRUD application that manages simple entities stored in a database, nothing but classic : JSP view, RequestMapping annotated controller, transactional service layer and DAO.
On an update, I need to know the previous values of my fields, because a business rule asks a for a test involving the old and new values.
So I am searching for a best practice on that use case.
I thing that spring code is way more extensively tested and more robust than my own, and I would like to do it the spring way as much as possible.
Here is what I have tried :
1/ load an empty object in controller and manage the update in service :
Data.java:
class Data {
int id; // primary key
String name;
// ... other fields, getters, and setters omitted for brevity
}
DataController
...
#RequestMapping("/data/edit/{id}", method=RequestMethod.GET)
public String edit(#PathVariable("id") int id, Model model) {
model.setAttribute("data", service.getData(id);
return "/data/edit";
}
#RequestMapping("/data/edit/{id}", method=RequestMethod.POST)
public String update(#PathVariable("id") int id, #ModelAttribute Data data, BindingResult result) {
// binding result tests omitted ..
service.update(id, data)
return "redirect:/data/show";
}
DataService
#Transactional
public void update(int id, Data form) {
Data data = dataDao.find(id);
// ok I have old values in data and new values in form -> do tests stuff ...
// and MANUALLY copy fields from form to data
data.setName(form.getName);
...
}
It works fine, but in real case, if I have many domain objects and many fields in each, it is quite easy to forget one ... when spring WebDataBinder has done it including validation in the controller without I have to write any single thing other than #ModelAttribute !
2/ I tried to preload the Data from the database by declaring a Converter
DataConverter
public class DataConverter<String, Data> {
Data convert(String strid) {
return dataService.getId(Integer.valueOf(strid));
}
}
Absolutely magic ! The data if fully initialized from database and fields present in form are properly updated. But ... no way to get the previous values ...
So my question is : what could be the way to use spring DataBinder magic and to have access to previous values of my domain objects ?
You have already found the possible choices so i will just add some ideas here ;)
I will start with your option of using a empty bean and copying the values over to a loaded instance:
As you have shown in your example it's an easy approach. It's quite easily adaptable to create a generalized solution.
You do not need to copy the properties manually! Take a look at the 'BeanWrapperImpl' class. This spring object allows you to copy properties and is in fact the one used by Spring itself to achieve it's magic. It's used by the 'ParameterResolvers' for example.
So copying properties is the easy part. Clone the loaded object, fill the loaded object and compare them somehow.
If you have one service or just several this is the way to go.
In my case we needed this feature on each entity. Using Hibernate we have the issue that an entity might not only change inside a specific service call, but theoretically all over the place..
So I decided to create a 'MappedSuperClass' which all entities need to extend. This entity has a 'PostLoad' event listener which clones the entity in a transient field directly after loading. (This works if you don't have to load thousands of entities in a request.) Then you need also the 'PostPersist' and 'PostUpdate' listeners to clone the new state again as you probably don't reload the entity before another modification.
To facilitate the controller mapping I have implemented a 'StringToEntityConverter' doing exactly what you did, just generalized to support any entity type.
Finding the changes in a generalized approach will involve quite a bit of reflection. It's not that hard and I don't have the code available right now, but you can also use the 'BeanWrapper' for that:
Create a wrapper for both objects. Get all 'PropertyDescriptors' and compare the results. The hardest part is to find out when to stop. Compare only the first level or do you need deep comparison?
One other solution could also be to rely on Hibernate Envers. This would work if you do not need the changes during the same transaction. As Envers tracks the changes during a flush and creates a 'Revision' you can "simply" fetch twp revisions and compare them.
In all scenarios you will have to write a comparison code. I'm not aware of a library but probably there is something around in the java world :)
Hope that helps a bit.

Categories