[security-dev] IDM Configuration API
Anil Saldhana
Anil.Saldhana at redhat.com
Tue Nov 6 16:33:32 EST 2012
Shane - the configuration API is important. Go ahead.
On 11/06/2012 10:34 AM, Jason Porter wrote:
> +1 at all sounds good to me.
>
>
> On Tue, Nov 6, 2012 at 3:08 AM, Shane Bryzak <sbryzak at redhat.com
> <mailto: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 <mailto: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 <http://keyserver.net>,
> pgp.mit.edu <http://pgp.mit.edu>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/security-dev/attachments/20121106/ef691a12/attachment.html
More information about the security-dev
mailing list