[wildfly-dev] Preparation for requirements and capabilities.
Brian Stansberry
brian.stansberry at redhat.com
Wed Mar 25 10:44:41 EDT 2015
On 3/25/15 9:36 AM, Darran Lofthouse wrote:
>
>
> On 25/03/15 14:28, Brian Stansberry wrote:
>> On 3/25/15 7:01 AM, Darran Lofthouse wrote:
>>>
>>>
>>>
>>> On 24/03/15 20:11, Brian Stansberry wrote:
>>> > On 3/24/15 1:08 PM, Darran Lofthouse wrote:
>>> >> My first questions in this area are - What are the constraints going to
>>> >> be about unique naming of capabilities?
>>> >
>>> > They must be namespaced. See
>>> >
>>> https://developer.jboss.org/wiki/CoreAndSubsystemCapabilitiesAndRequirements.
>>> >
>>> > The ones we provide must be in the org.wildfly namespace, which is
>>> > reserved for us. Use org.wildfly.extension.xxxx for stuff this is
>>> > provided by an extension, and isn't part of the kernel.
>>> >
>>> > (OT: I'm going to start using the term 'kernel' to mean what used to be
>>> > called the 'core' since now WildFly Core means the kernel plus a few
>>> > subsystems.)
>>>
>>> (OT: Personally I wish kernel was it's own build )
>>>
>>> >
>>> >> Will the implementation / API
>>> >> provide methods a subsystem can use to help enforce this?
>>> >>
>>> >
>>> > The OperationContext will enforce uniqueness. I don't think a subsystem
>>> > will help enforce this; the subsystem authors will just create a
>>> > reasonable namespace and stick to it.
>>>
>>> I may be thinking of this the opposite way around, or it may be that my
>>> capabilities are more ingrained with the application server as a whole.
>>>
>>> In the case of Elytron I think we have a successful API/SPI separation
>>> if we can say the Elytron Subsystem is optional, primarily this gives us
>>> two different situations: -
>>> - No capabilities provided and nothing requiring them - essentially a
>>> completely unsecured server.
>>> - An alternative subsystem providing all of the capabilities, maybe
>>> this is a pure KeyCloak server or maybe an ISV wants the security
>>> tightly built on their product.
>>>
>>> As I type this having the namespace defined by the subsystem is probably
>>> not an issue provided that every place say a security realm can be
>>> referenced this is a qualified reference including the namespace. Also
>>> the discovery of available security realms would need to take into
>>> account different namespaces being available.
>>>
>>
>> I think it's best to decouple the concepts of capabilities and subsystems.
>>
>> A capability is a form of API/SPI. It has a name, and it can provide an
>> API. (Note that this API is not limited to service injection; we do
>> other things in other cases.)
>>
>> A subsystem can provide a capability, but that doesn't mean it has to
>> "own" the capability. There can be a capability named
>> org.wildfly.extension.security.security-realm that is owned by the
>> WildFly dev team, but that doesn't mean the Elytron subsystem has to own
>> it. Someone else could provide it as well. This is logically analogous
>> to some library providing an API/SPI and then also an impl.
>
> That part sounds perfect for me. The capabilities we are thinking about
> here will be integral to the whole application server.
>
>> If the user configures two providers of the same capability in the same
>> context, it's a configuration error. The server will reject that. Over
>> time hopefully provisioning tooling will come along that will reject it
>> in advance.
>
> The case I have now is say the Elytron subsystem is installed and the
> KeyCloak subsystem is installed - it is quite conceivable that both
> would provide capabilities for
> 'org.wildfly.extension.security.security-realm'
>
That's fine so long as they don't appear in the configuration in the
same "context". Context meaning the same profile. A domain can have
both, just not in the same profile. A standalone server of course only
has one profile.
>> If some consumer of capabilities just wants Service<SecurityRealm> and
>> doesn't care which of a menu of capabilities provides it, I consider
>> that to be corner case detail, and something to be handled by that
>> consumer (by registering an optional requirement for each and using
>> whichever is available.)
>>
>>
>>> (OT: Wonder if we should think about access control here, I am waiting
>>> till I have the majority of the model in place to really look into it
>>> but we do have the issue of no longer being able to tell which parts of
>>> security are app and which parts are management)
>>>
>>> >> When it comes to resource definitions the definition can either be
>>> >> focused on the implementation behind the service or the type the service
>>> >> returns. My preference is to focus on the implementation.
>>> >>
>>> >> As an example I have a few different security realm implementations: -
>>> >>
>>> >> keystore-realm=*
>>> >> ldap-realm=*
>>> >> jaas-realm=*
>>> >>
>>> >> All of these would register a service that returns 'SecurityRealm' so
>>> >> 'SecurityRealm' would be the capability.
>>> >>
>>> >> So this is really the basis of my question as now the model does not
>>> >> enforce unique names. The reason for this type of split is so each can
>>> >> have it's own set of attribute definitions.
>>> >>
>>> >> If I turned this on it's head and have: -
>>> >>
>>> >> security-realm=*
>>> >>
>>> >> Now the model will enforce unique names within my subsystem but I have
>>> >> lost the association of type specific attributes. A security realm
>>> >> could support all attribute types but now it becomes hard to work with
>>> >> and understand what does what depending on the type. Or I could add a
>>> >> child resource for type specific settings but that moves away from my
>>> >> aim of a 1:1 mapping between resource and service.
>>> >>
>>> >> Although the model enforces unique names this is specific to my
>>> >> subsystem only, if another subsystem is also capable of supplying
>>> >> SecurityRealm implementations duplicates are again possible.
>>> >>
>>> >
>>> > Within a given context (i.e. a standalone server or a domain profile)
>>> > some other subsystem providing a capability with the same name will not
>>> > be allowed. If someone else wants to provide access to
>>> > Service<SecurityRealm> for some unrelated reason then they need to
>>> > provide their own capability name. If they are actually another
>>> > implementation of the same capability, then the user has to pick one or
>>> > the other within a context.
>>> >
>>> >> So overall my preference would be let capabilities and requirements
>>> >> worry about naming constraints and leave subsystem implementations to
>>> >> focus on understandable typed resources.
>>> >>
>>> >
>>> > That's fine. If keystore-realm=* et al are all providing instances of
>>> > the same capability, then the OperationContext can enforce that as part
>>> > of model validation by detecting duplicate instance names registered
>>> > within a single capability namespace.
>>> >
>>> > Having keystore-realm=*, ldap-realm=*, jaas-realm=* all registering
>>> > instance names in the same capability namespace will add some complexity
>>> > to the validation though, so thanks for pointing that use case out. The
>>> > complexity is discriminating your use case (legal) from two completely
>>> > different subsystems using the same namespace in the same context
>>> > (illegal). A possible solution is the parent resource for those is what
>>> > declares that it provides capability org.wildfly.extension.xxx and then
>>> > the kernel accepts instance name registrations from children, while
>>> > rejecting them from non-children.
>>> >
>>> >> Regards,
>>> >> Darran Lofthouse.
>>> >>
>>> >>
>>> >>
>>> >>
>>> >> On 24/03/15 14:41, Brian Stansberry wrote:
>>> >>> On 3/24/15 9:33 AM, Darran Lofthouse wrote:
>>> >>>>
>>> >>>>
>>> >>>> On 24/03/15 14:24, Brian Stansberry wrote:
>>> >>>>> On 3/19/15 12:08 PM, Darran Lofthouse wrote:
>>> >>>>>> On 19/03/15 10:20, Darran Lofthouse wrote:
>>> >>>>>>> Assuming the title still covers the scenarios I have in mind is
>>> there
>>> >>>>>>> anything we can be doing now to prepare for requirements and
>>> >>>>>>> capabilities support to make transitioning easier once it is
>>> available.
>>> >>>>>>>
>>> >>>>>>> As an example within Elytron we will have a number of services that
>>> >>>>>>> define either standard types or types defined by API that we
>>> want to
>>> >>>>>>> inject - is there anything we can do today for subsystems that
>>> want to
>>> >>>>>>> say "I want a type X, named Y injected here" whilst minimising
>>> >>>>>>> interaction with and knowledge of the Elytron subsystem.
>>> >>>>>>
>>> >>>>>> For the service naming issue I have one idea, I create a utility
>>> class
>>> >>>>>> in wildfly-core with the following method: -
>>> >>>>>>
>>> >>>>>> public static ServiceName createServiceName(Class<?> type,
>>> >>>>>> String simpleName);
>>> >>>>>>
>>> >>>>>> The type here is the type that the service returns, this methods
>>> >>>>>> constructs a ServiceName taking into account the class name of
>>> the type
>>> >>>>>> and the supplied simpleName which really is just it's reference.
>>> >>>>>>
>>> >>>>>> Within the Elytron subsystem I install services by using this
>>> method to
>>> >>>>>> construct the names.
>>> >>>>>>
>>> >>>>>> For any other service that depends on one of these types the
>>> same method
>>> >>>>>> is used when creating the dependency.
>>> >>>>>>
>>> >>>>>> This way details of the Elytron subsystem do not leak out to other
>>> >>>>>> subsystems.
>>> >>>>>>
>>> >>>>>
>>> >>>>> I like the notion of both the capability code and the requiring code
>>> >>>>> turning over the mechanics of service name creation to the core. I
>>> >>>>> expect that will go into the OperationContext though, as it has the
>>> >>>>> knowledge of what capabilities exist. If it's purely a mechanical
>>> >>>>> function though with no validation required it could just go in some
>>> >>>>> static method somewhere, but it's likely in the real use cases there
>>> >>>>> will be some validation.
>>> >>>>>
>>> >>>>> I don't see a type as being valid data for creating a
>>> ServiceName. There
>>> >>>>> isn't a 1:1 correspondence between a type and the various things that
>>> >>>>> can provide services whose value is of that type. Simplest case being
>>> >>>>> Service<Void>, but I bet we have some Service<String> out there.
>>> >>>>>
>>> >>>>> If we limit a capability to providing just a single type for
>>> injections,
>>> >>>>> then it can just be:
>>> >>>>>
>>> >>>>> public ServiceName getServiceName(String capability, String
>>> instanceName)
>>> >>>>>
>>> >>>>> A capability provides a namespace, as does the prefix for a
>>> ServiceName
>>> >>>>> so it seems reasonable enough to me to reuse one for the other.
>>> >>>>> Particularly if it's all hidden behind a method the core provides.
>>> >>>>>
>>> >>>>> I was a bit reluctant to limit a capability to providing just a
>>> single
>>> >>>>> injection type, as there are some cases where it's a bit fine
>>> grained.
>>> >>>>> For example IIOP provides both an ORB and a CORBA
>>> NamingContextExt. But
>>> >>>>> I don't think there are enough such cases to outweigh the simplicity
>>> >>>>> advantages of having a single injection type per capability.
>>> >>>>
>>> >>>> +1 Take my suggestion extremely lightly, that was only going to be a
>>> >>>> temporary step towards being capability based - from your other e-mail
>>> >>>> it sounds like that is going to be actively developed now so I can
>>> just
>>> >>>> use the real thing.
>>> >>>>
>>> >>>
>>> >>> Yes, it will be. I did a fair amount last summer/fall but then hit a
>>> >>> point where I wanted to let ideas percolate, plus I had to do a lot of
>>> >>> other tasks. But I think enough percolation has happened (including
>>> your
>>> >>> helpful suggestion above) and the list other stuff I've had to do is
>>> >>> getting short.
>>> >>>
>>> >>>> I am at the point now where I am starting to wire things together
>>> in the
>>> >>>> server and have just started an incubation fork of wildfly-core for my
>>> >>>> development so let me know if there is anything you want me to try
>>> out.
>>> >>>>
>>> >>>
>>> >>> Thanks; I'll do that for sure.
>>> >>>
>>> >>>>>>> Secondly is there anything we can do at the model level regarding
>>> >>>>>>> assisting the user with referential integrity, as an example
>>> say I am
>>> >>>>>>> writing an attribute using the CLI called 'keystore', this is
>>> going to
>>> >>>>>>> be a reference to a named KeyStore - how about some form of op
>>> >>>>>>> associated with that attribute that can dynamically generate
>>> the list of
>>> >>>>>>> accepted values on demand, e.g. by querying the model and
>>> finding out
>>> >>>>>>> which KeyStores are actually available.
>>> >>>>>>>
>>> >>>>>>> Regards,
>>> >>>>>>> Darran Lofthouse.
>>> >>>>>>> _______________________________________________
>>> >>>>>>> wildfly-dev mailing list
>>> >>>>>>> wildfly-dev at lists.jboss.org
>>> >>>>>>> https://lists.jboss.org/mailman/listinfo/wildfly-dev
>>> >>>>>>>
>>> >>>>>> _______________________________________________
>>> >>>>>> wildfly-dev mailing list
>>> >>>>>> wildfly-dev at lists.jboss.org
>>> >>>>>> https://lists.jboss.org/mailman/listinfo/wildfly-dev
>>> >>>>>>
>>> >>>>>
>>> >>>>>
>>> >>>> _______________________________________________
>>> >>>> wildfly-dev mailing list
>>> >>>> wildfly-dev at lists.jboss.org
>>> >>>> https://lists.jboss.org/mailman/listinfo/wildfly-dev
>>> >>>>
>>> >>>
>>> >>>
>>> >> _______________________________________________
>>> >> wildfly-dev mailing list
>>> >> wildfly-dev at lists.jboss.org
>>> >> https://lists.jboss.org/mailman/listinfo/wildfly-dev
>>> >>
>>> >
>>> >
>>>
>>> _______________________________________________
>>> wildfly-dev mailing list
>>> wildfly-dev at lists.jboss.org
>>> https://lists.jboss.org/mailman/listinfo/wildfly-dev
>>>
>>
>>
> _______________________________________________
> wildfly-dev mailing list
> wildfly-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/wildfly-dev
>
--
Brian Stansberry
Senior Principal Software Engineer
JBoss by Red Hat
More information about the wildfly-dev
mailing list