[security-dev] IDM Configuration API

Jason Porter lightguard.jp at gmail.com
Tue Nov 6 11:34:48 EST 2012


+1 at all sounds good to me.


On Tue, Nov 6, 2012 at 3:08 AM, Shane Bryzak <sbryzak at redhat.com> wrote:

> Hey guys,
>
> For the past few days I've been wracking my brain trying to come up with
> a design for the IDM configuration API that doesn't suck, and allows
> easy configuration in both Java SE and EE environments while maintaining
> separation between the API and implementation.  I think I've come up
> with something that's quite flexible and extensible, so I'd like to run
> it past everyone for some feedback.
>
> The starting point for configuring the Identity Management API is a
> concrete class called IdentityConfiguration:
>
> public class IdentityConfiguration {
>      private List<IdentityStoreConfiguration> configuredStores = new
> ArrayList<IdentityStoreConfiguration>();
>      public List<IdentityStoreConfiguration> getConfiguredStores() {
>          return configuredStores;
>      }
>      public void addStoreConfiguration(IdentityStoreConfiguration config) {
>          configuredStores.add(config);
>      }
> }
>
> This class simply provides a holder for one or more
> IdentityStoreConfiguration(s), an abstract class that provides the
> basics for configuring an IdentityStore:
>
> public abstract class IdentityStoreConfiguration {
>      private final Map<String,String> properties = new
> HashMap<String,String>();
>      private final Set<Feature> supportedFeatures = new HashSet<Feature>();
>      public Set<Feature> getSupportedFeatures() {
>          return supportedFeatures;
>      }
>      public void addSupportedFeature(Feature feature) {
>          supportedFeatures.add(feature);
>      }
>      public void removeSupportedFeature(Feature feature) {
>          supportedFeatures.remove(feature);
>      }
>      public void setProperty(String name, String value) {
>          properties.put(name, value);
>      }
>      public String getPropertyValue(String name) {
>          return properties.get(name);
>      }
> }
>
> Each IdentityStore implementation (such as JPAIdentityStore,
> LDAPIdentityStore, etc) should have a corresponding
> IdentityStoreConfiguration implementation that provides an API for
> setting specific property values for its IdentityStore.  For example,
> this is the one for JPAIdentityStore which allows a number of entity
> classes to be set:
>
> public class JPAIdentityStoreConfiguration extends
> IdentityStoreConfiguration {
>      private Class<?> identityClass;
>      private Class<?> membershipClass;
>      private Class<?> credentialClass;
>      private Class<?> attributeClass;
>      public Class<?> getIdentityClass() {
>          return identityClass;
>      }
>      public void setIdentityClass(Class<?> identityClass) {
>          this.identityClass = identityClass;
>      }
>      public Class<?> getCredentialClass() {
>          return credentialClass;
>      }
>      public void setCredentialClass(Class<?> credentialClass) {
>          this.credentialClass = credentialClass;
>      }
>      public Class<?> getMembershipClass() {
>          return membershipClass;
>      }
>      public void setMembershipClass(Class<?> membershipClass) {
>          this.membershipClass = membershipClass;
>      }
>      public Class<?> getAttributeClass() {
>          return attributeClass;
>      }
>      public void setAttributeClass(Class<?> attributeClass) {
>          this.attributeClass = attributeClass;
>      }
> }
>
> The IdentityStore-specific configurations are intended to be part of the
> API, so they should be placed in the API module within the
> org.picketlink.idm.config package.
>
> After creating an IdentityConfiguration, you can create an
> IdentityManager and provide the configuration via the bootstrap() method:
>
> IdentityConfiguration identityConfig = new IdentityConfiguration();
> JPAIdentityStoreConfiguration storeConfig = new
> JPAIdentityStoreConfiguration();
> // snip storeConfig configuration
>
> identityConfig.addStoreConfiguration(storeConfig);
>
> IdentityManager identityManager = new DefaultIdentityManager();
> identityManager.bootstrap(identityConfig, new
> DefaultIdentityStoreInvocationContextFactory(null));
>
> The reason we use bootstrap() instead of performing configuration in the
> constructor is so the developer has a chance to override the
> IdentityStoreFactory.  This is an SPI interface that defines a couple of
> methods which are used to control which IdentityStoreConfigurations
> correspond to which IdentityStore.
>
> public interface IdentityStoreFactory {
>      /**
>       * Creates an instance of an IdentityStore using the provided
> configuration
>       *
>       * @param config
>       * @return
>       */
>      IdentityStore createIdentityStore(IdentityStoreConfiguration config);
>
>      /**
>       * Maps specific implementations of IdentityStoreConfiguration to a
> corresponding
>       * IdentityStore implementation.
>       *
>       * @param configClass
>       * @param storeClass
>       */
>      void mapConfiguration(Class<? extends IdentityStoreConfiguration>
> configClass,
>              Class<? extends IdentityStore> storeClass);
> }
>
> By default, the DefaultIdentityManager will create and use an instance
> of DefaultIdentityStoreFactory - this factory knows about all the
> built-in IdentityStore implementations and can create IdentityStore
> instances based on their corresponding IdentityStoreConfiguration.  If a
> developer wished to provide their own IdentityStore though (or override
> the behaviour of one of the built-in ones) then we need to provide a
> hook to allow them to override the default factory with their own.  This
> is provided by the IdentityManager.setIdentityStoreFactory() method - by
> invoking this method with a new IdentityStoreFactory the developer can
> provide an alternative factory for creating IdentityStore instances
> based on non built-in configurations before bootstrap() is called.
>
> Here's an example where the built-in identity stores are supplemented
> with support for a native Hibernate-based identity store:
>
> IdentityManager identityManager = new DefaultIdentityManager();
>
> DefaultIdentityStoreFactory factory = new DefaultIdentityStoreFactory();
> factory.mapConfiguration(HibernateIdentityStoreConfiguration.class,
> HibernateIdentityStore.class);
> identityManager.setIdentityStoreFactory(factory);
>
> identityManager.bootstrap(identityConfig, new
> DefaultIdentityStoreInvocationContextFactory(null));
>
> The last piece of the puzzle is the second parameter to the bootstrap()
> method.  This parameter should be an instance of
> IdentityStoreInvocationContextFactory (I know, it's a mouthful), an SPI
> interface that declares a single method:
>
> public interface IdentityStoreInvocationContextFactory {
>      IdentityStoreInvocationContext getContext(IdentityStore store);
> }
>
> The implementation of this interface is responsible for creating
> IdentityStoreInvocationContext instances, which are passed as a
> parameter value to pretty much all of the IdentityStore methods and
> allow the IdentityStore implementation to be shared between multiple
> threads (i.e. a stateless design).  The IdentityStoreInvocationContext
> is responsible for providing the IdentityStore with any state (besides
> the IdentityStore configuration) required to execute its requested
> operation.  It also provides a gateway to the event bridge, which allows
> events to be raised during an IdentityStore operation and propagated to
> any environment, such as the CDI event bus.  The
> IdentityStoreInvocationContext implementation/s are currently still a
> work in progress, however the basic API should not change.
>
> This essentially wraps up the description of the configuration API. What
> I haven't touched upon yet are the builders (classes that parse a
> configuration source such as a file to create an
> IdentityStoreConfiguration) however I'm hoping Anil that you might want
> to have a go at this.
>
> With these changes comes a small TO-DO list:
>
> 1) IdentityStoreConfiguration implementations should be created in the
> API module within the org.picketlink.idm.config package for each of the
> IdentityStore implementations (we already have one for LDAP, but it
> needs to be moved and possibly renamed to LDAPIdentityStoreConfiguration
> for consistency).
>
> 2) During the course of the refactor I had to provide workarounds for
> many of the tests, and I also managed to totally break quite a few
> others.  The test suite needs a quick review to see why the tests are
> broken, and once configurations are provided for the other identity
> stores the workarounds can be removed.
>
> 3) The getFeatureSet() method should be correctly implemented for all
> IdentityStores.  With the change to the configuration API we now have
> proper support for partitioning, and it's important that this method
> accurately reflect the underlying capabilities of the IdentityStore
> implementation for this feature to work correctly.
>
> Thanks for listening, and I'm looking forward to getting some feedback
> on this!
>
> Shane
> _______________________________________________
> security-dev mailing list
> security-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/security-dev
>



-- 
Jason Porter
http://lightguard-jp.blogspot.com
http://twitter.com/lightguardjp

Software Engineer
Open Source Advocate

PGP key id: 926CCFF5
PGP key available at: keyserver.net, pgp.mit.edu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/security-dev/attachments/20121106/a623a3d0/attachment-0001.html 


More information about the security-dev mailing list