I am using the new Spring Security 3.1 and have a few questions to Spring Security ACL.
So let's say I have an object and want to define an ACL for it. I create an ACL Entry and want to asign it to a group of users; not a role (GrantedAuthoritySid), not one user (PrincipalSid), but a group of users. I have researched everywhere for an example but was unable to find any. Can you please point me to an example or the class that would help me in this scenario?
So now I want to create a second object that is related to the first object (it should apply for the same users).
This could be a status update for the first object for example. My GrantedAuthority or Principal has a different mask of permisions for the second object.
Also the first object has 2 GrantedAuthorities (2 ACLEntries), and the status update has just one. If I use ACL inheritance the permision sets for the first object do not match the permision set for the second.
My question is how can I model this so that the GrantedAuthorities for the two objects are automatically kept consistent while retaining different permision masks. One idea is to use a composite pattern to link the GrantedAuthority of the second object on the GrantedAuthority of the first object (instead of linking it to users).
An ACL has a owner. What is the owner for? What role does it play for the ACL or for the ACL entries?
It's kind of complicated. I reverse engineered the Spring source code to understand the principle and it took me a lot of time. I can't exactly tell you how I implemented it (because it's very specific for the project I work on) but will try to give you a starting point.
What I did was:
Implement a custom org.springframework.security.acls.sid.Sid. This Sid references not an authority or user but a kind of groupobject which has an id and references two different objects. To use this groupobject as an Sid you have to create an ACL_Sid-record with the id of the object as ACL_sid.sid. ACL_sid.principal has to be an integer other than 0 or 1 which has to be checked for in a test in the custom LookupStrategy (see below and the Spring sourcecode).
Extend org.springframework.security.acls.sid.SidRetrievalStrategyImpl to retrieve the custom Sid's from the database.
Implement a custom org.springframework.security.acls.jdbc.LookupStrategy. I copied an existing implementation (because the class was final) and modified it for my needs.
Wired everything together in the spring configuration because the default Spring ACL config needs to no which classes it had to use (and not the defaults)
Look at the Spring source code and see how it's done.
To assign an object to a group of users, there should be an ACL entry for each user for the same object. This may lead to a considerably large amount of ACL records.
Related
I am currently reading about DDD and have a issue how to implement a certain validation.
Scenario:
I have an entity Group that contains a list of Members which in turn consists of a User and a MemberState (Member, Admin). The entity has a method MakeAdmin(User user) that turns a member into an admin.
The rule is: Only if the current user is admin of the group, it is allowed to turn the member to an admin.
I have three possible implementations in mind, with some caveats each.
Variant 1
Group enitity gets a dependency IUserContext injected via constructor to get the current user. With that the entity can check if the current user is admin and is allowed to switch the member state.
Caveat: I don't like that the domain entity has such a dependency injected and I don't think that is correct in a DDD view.
Variant 2
Method MakeAdmin() gets an additional parameter which turns it into MakeAdmin(User user, User currentUser). That removes the requirement for the IUserContext dependency in the entity.
Caveat: I am not sure if it is correct at all that the entity validates this rule, because it is not really an invariant of the entity.
Variant 3
Validate this rule in an application service, and only call MakeAdmin(User user) if validation passed.
Caveat: I consider the rule domain specific, so I think it is not correct to put it in application layer.
So what would be the best option, or is there some totally different variant?
My suggestion would be to go with your third option: Authorise access in the application/integration layer and then call into the domain.
This goes for any domain functionality really. The domain should not concern itself with whether the action may or may not be performed based on authorisation but rather only with domain concerns. If that authorisation action happens to be a domain concern in a particular Identity & Access Control bounded context that it would make sense but you would not run into those too often.
I have 2 domain classes. One of them is User and the other is SuperUser. The super user contains some extra fields, and SuperUser inherits from User. (Also to note: User has the mapping to set inheritTableHeirachy set to false).
How can I cast the existing User instance object to a SuperUser? Is there a way that I can pass it in the SuperUser constructor?
I want to keep the reference to the original user, and I want to add the extra properties of SuperUser to the SuperUser table.
There is the way via properties. You maybe want to eradicate the ID afterwards or filter already before, what you don't need (it's a map). E.g.
new SuperUser(theUser.properties)
Since this only "copies" the same property names, there is no protection against setting "stupid" things. Both objects don't have to be of the same class hierarchy etc. It is just calling the c'tor for maps with a map.
A more structured way would be the introduction of an adaptor for this case.
I am working on a project where we have requirement to provide field level access to users.
Example:
Suppose there is an entity named employee with several fields
The application should allow secure access at the field level of the entity.
According to the access user is allowed to edit / read the fields.
We have thought of an implementation using spring acl but it provides instance level security.
Could someone please let know an elegant way to implement it?
Thanks in advance.
Take a look at the fields plugin.
It allows you to control how individual fields are rendered.
You could implement a security check within each field's _field.gsp fragment, or you could override the plugin's taglib's f:all method and add a security check there if you prefer.
You could use the plugin for that, but you'd need to do some extra work. The ACL support in Spring Security basically lets you say "grant permission x on object instance y (of type "foo") with id z to person p". There is an example permissions class with standard instances like Read, Write, Admin, etc., but the underlying infrastructure only works with the numbers 1, 2, 4, 8, etc. so you can easily define your own permission types - they're really just mappings of human-readable names to numbers. You typically grant permissions on domain object instances, but under the hood the names of the domain classes are just strings, so you could store any type name there. And the ids can be any value, e.g. a number or a string.
You wouldn't be able to use the #PreAuthorize and #PostFilter annotations on service methods, but you can still query the ACL beans to see if, given a field or whatever you want, the currently authenticated user is allowed to perform some action.
I've been learning the ASP.NET MVC framework using the Apress book "Pro ASP.NET MVC Framework" by Steven Sanderson. To that end I have been trying out a few things on a project that I am not that familar with but are things that I thing I should be doing, namely:
Using repository pattern to access my database and populate my domain/business objects.
Use an interface for the repository so it can be mocked in a test project.
Use inversion of control to create my controllers
I have an MVC web app, domain library, test library.
In my database my domain items have an Id represented as an int identity column. In my domain classes the setter is internal so only the repository can set it.
So my quandries/problems are:
Effectively all classes in the domain library can set the Id property, not good for OOP as they should be read-only.
In my test library I create a fake repository. However since it's a different assembly I can't set the Id properties on classes.
What do others do when using a database data store? I imagine that many use an integer Id as unique identifier in the database and would then need to set it the object but not by anything else.
Can't you set your objects' IDs during construction and make them read-only, rather than setting IDs through a setter method?
Or do you need to set the ID at other times. If that's the case, could you explain why?
EDIT:
Would it be possible to divorce the ID and the domain object? Does anything other than the repository need to know the ID?
Remove the ID field from your domain object, and have your repository implementations track object IDs using a private Dictionary. That way anyone can create instances of your domain objects, but they can't do silly things with the IDs.
That way, the IDs of the domain objects are whatever the repository implementation decides they are - they could be ints from a database, urls, or file names.
If someone creates a new domain object outside of the repository and say, tried to save it to your repository, you can look up the ID of the object and save it as appropriate. If the ID isn't there, you can either throw an exception to say you need to create the object using a repository method, or create a new ID for it.
Is there anything that would stop you from using this pattern?
you can use the InternalsVisibleTo attribute. It will allow the types from an assembly to be visible from the tests (provided they are in different assemblies).
Otherwise you can leave the property read-only for the external objects but in the same time have a constructor which has an ID parameter and sets the ID property. Then you can call that constructor.
Hope this helps.
in our new software project, we have the following requirement: A webpage shall show a set of data. This data shall be editable by some users (assigned to roles, i.e. manager), and only viewable by others. The tricky part is described by an example:
A User-page consists of address data and account information. The addess data shall be editable by the user and the manager and viewable by all users, while account information shall only be viewable by the actual user and the manager.
I have read a lot of information about SpringSecurity. It provides a very good framework to gran permissions on urls and methods and even domain classes. But what I need is field level ACLs. At least, that's what I think at the moment.
So, the question is: How to solve this problem using Grails?
Thanks a lot in advance,
Regards Daniel
Spring Security (Acegi Plugin) is definitely the way to go with Grails.
There is a taglib you can use that will allow a page to be different for different roles such as the following:
<g:ifUserHasRole roles="ROLE_ADMIN">
html code for extra fields
</g:ifUserHasRole>
Me, I'd encode it on the domain class, emulating the way GORM has you annotate the domain classes (static access = [field1: "ROLE_USER", field2: "ROLE_ADMIN,ROLE_USER"] as an example). Then build a method your controller could use to redact them for a given user. That method could use the domain class's annotations to decide how to redact it. Then, metaprogram it onto each of the domain classes the way plugins do.
Similarly, write the opposite method to restrict data bindings of params into the domain class, write your own data binding utility method, then metaprogram it onto each domain class as well.
Then you can just use instance.redact(user) or instance.bindData(params, user) to do what you want, and it's practically declarative syntax.
We have a similar situation and use both the ifUserHasRole tag in the gsp to drive the appropriate presentation and the we have a filter that enforces the rules based on the action being called. For example, on user controller we would only allow the management roles to call save action, or if the user.id is the same as the session.user.id. This seemed to be the best option for our situation.
What about creating an ACL class like this:
class ACL(val entry: Entry*) {
def isAccessAllowed(subject: String, permission: String): Boolean = ...
}
class Entry(val subject: String, val permission: String*)
usage:
new ACL(
new Entry("dave", "read", "write"),
new Entry("linda", "read")
)
(This example is in Scala, because I found it more expressive in this case, but it should be easy to transfer it to Groovy.)
You would then connect an ACL object with the object to be protected.