[security-dev] IDM Configuration API

Shane Bryzak sbryzak at redhat.com
Sun Nov 11 19:08:25 EST 2012

On 11/09/2012 07:57 AM, Boleslaw Dawidowicz wrote:
> On Nov 6, 2012, at 11:10 PM, Shane Bryzak <sbryzak at redhat.com 
> <mailto:sbryzak at redhat.com>> wrote:
>> On 11/07/2012 07:35 AM, Boleslaw Dawidowicz wrote:
>>> Also +1. It looks really good.
>>> I assume the strategy to handle operations when two stores are 
>>> configured is IdentityManager implementation area. I wonder if we 
>>> should make this part also more flexible in some way. Not really 
>>> thinking about IdentityStoreRepository kind of design I had in 1.x 
>>> as it is probably a bit too much. However it should be at least easy 
>>> to extend DefaultIdentityManager to add some customizations to how 
>>> specific operations are handled. Or we should have something like 
>>> GenericIdentityManager for such purpose.
>> This feature (which I've been referring to as partitioning) is 
>> supported by requiring each configured IdentityStore to provide 
>> metadata as to which features are supported, via the getFeatureSet() 
>> method:
>> Set<Feature> getFeatureSet();
>> Feature is an enum defining all currently supported identity 
>> management operations:
>>     public enum Feature { createUser, readUser, updateUser, deleteUser,
>>                           createGroup, readGroup, updateGroup, 
>> deleteGroup,
>>                           createRole, readRole, updateRole, deleteRole,
>>                           createMembership, readMembership, 
>> updateMembership, deleteMembership,
>>                           validateCredential, updateCredential,
>>                           all }
>> When an IdentityManager method is invoked, the correct IdentityStore 
>> for the required operation is selected based on its supported feature 
>> set.  Here's an example of this, in the createUser() method:
>>     @Override
>>     public User createUser(String name) {
>>         User user = new SimpleUser(name);
>>         IdentityStore store = getStoreForFeature(Feature.createUser);
>> store.createUser(getContextFactory().getContext(store), user);
>>         return user;
>>     }
>> The getStoreForFeature() method iterates through the configured 
>> stores and returns the one that supports the specified Feature, in 
>> this example Feature.createUser.  This way we can configure multiple 
>> stores with one of them providing user-related operations, one 
>> providing group and role operations, and so forth.
> This will still not cover all use cases.
> You have few stores that support credential validation and implement 
> some kind of strategy like in pam. I'm not saying that spi should be 
> more complex - no I think it is rather perfect for the balance between 
> complexity and features. Just pointing out that people will need to 
> extend IdentityManager to introduce some more complex multi store 
> behaviors. Implementation should be done with it in mind. Avoid 
> private methods and so on.

It should be relatively simple to extend the default IdentityManager and 
override this behaviour if the developer wants something else.

>>> Looking forward to see your ideas around design of event handling 
>>> part. I think it will be critical to truly pluggable and extendable.
>> This feature was quite simple.  I've opted to go with the "class as 
>> an event" model, where each event type is represented by a POJO 
>> containing the relevant event state. For example, the following event 
>> is raised when a new user is created:
>> public class UserCreatedEvent extends AbstractBaseEvent {
>>     private User user;
>>     public UserCreatedEvent(User user) {
>>         this.user = user;
>>     }
>>     public User getUser() {
>>         return user;
>>     }
>> }
>> In this example, the event class contains a reference to the User 
>> that was created.  In addition to this, each event class should 
>> extend AbstractBaseEvent which also provides an event context:
>> public abstract class AbstractBaseEvent {
>>     private EventContext context = new EventContext();
>>     public EventContext getContext() {
>>         return context;
>>     }
>> }
>> The EventContext provides a general purpose mechanism for passing 
>> arbitrary state:
>> public class EventContext {
>>     private Map<String,Object> context;
>>     public Object getValue(String name) {
>>         return context != null ? context.get(name) : null;
>>     }
>>     public void setValue(String name, Object value) {
>>         if (context == null) {
>>             context = new HashMap<String,Object>();
>>         }
>>         context.put(name, value);
>>     }
>>     public boolean contains(String name) {
>>         return context != null && context.containsKey(name);
>>     }
>>     public boolean isEmpty() {
>>         return context == null || context.isEmpty();
>>     }
>> }
>> It is via the EventContext that we can pass IdentityStore 
>> implementation-specific state (for example the actual entity bean 
>> instance that was persisted to the database in the case of a JPA 
>> backed IdentityStore) or any additional state that might be relevant 
>> to the event.
>> As for bridging the event itself, the IdentityStoreInvocationContext 
>> provides access to the EventBridge via the getEventBridge() method:
>> EventBridge getEventBridge();
>> This is an extremely simple interface declaring just a single method:
>> public interface EventBridge {
>>     void raiseEvent(Object event);
>> }
>> The idea here is that you can provide an EventBridge implementation 
>> tailored for the environment that you're running in.  In an EE6 
>> environment, this is a piece of cake as we just pass the event 
>> straight on through to the CDI event bus.
>> That pretty much sums up event handling.
> Looks pretty simple indeed. What I had in mind was something with post 
> and per operation events but I guess that if needed those would fit 
> this design right? It more seems about defining valid event types and 
> raising points.
> I would like to be able to have access to full context - not just the 
> single store. Use case is for example to synchronize or propagate 
> objects from one identity store into other one in case of specific 
> operation.

Pre and post operation events will fit this design easily, yes. 
Propagation should be possible by creating a 'wrapper' IdentityStore 
that synchronizes identity state from one of the wrapped stores into 
another (I wouldn't base this on the event API).  I'm not quite 
convinced that synchronization is such a useful thing though, could you 
enlighten me with a use case where this would be required?

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/security-dev/attachments/20121112/bc902b3a/attachment.html 

More information about the security-dev mailing list