Exposing service-level security meta-information
dward May 6, 2013 1:05 PMThe purpose of SWITCHYARD-1414 is to allow for multiple security configuration sections within a switchyard.xml, and be able to reference a named section from a component service or component reference.
So basically, instead of this, where one security configuration section applies to all services within that deployment:
<switchyard> <composite> <!-- all services --> </composite> <domain> <security/><!-- applies to all services --> </domain> </switchyard>
We should do this, where you can reference a security configuration by name (or have a nameless "default" security configuration):
<switchyard> <composite> <service></service> <!-- multiple of these --> <component> <!-- multiple of these --> <implementation.xxx/> <service name="xxx" requires="confidentiality clientAuthentication authorization" security="foo"> <interface.java/> </service> </component> </composite> <domain> <securities> <security/> <security name="foo"/> <security name="bar"/> </securities> </domain> </switchyard>
Multiple services can in this way share the same security configuration.
Now for the major point of this discussion thread...
Previously, the single security configuration was held internally inside the ServiceDomain implementation (DomainImpl). Our org.switchyard.bus.camel.processors.Processors enum would create a Processor implementation, wrapping our SecurityHandler, and passing in the security configuration based on the ServiceDomain's exposure of the "ServiceSecurity" interface, like this:
SECURITY { public Processor create(ServiceDomain domain) { return wrap(new SecurityHandler(domain.getServiceSecurity())); } }
We obviously can't do this anymore, as a specific ServiceSecurity is now aligned with specific Services, not "globally" for the entire ServiceDomain. So, we can only do this:
SECURITY { public Processor create(ServiceDomain domain) { return wrap(new SecurityHandler()); } }
To handle this, on my branch, I've decided to make an org.switchyard API change, specifically adding access to the ServiceSecurity to our org.switchyard.Service interface:
public interface Service { ServiceInterface getInterface(); ServiceDomain getDomain(); ServiceSecurity getSecurity(); List<Policy> getRequiredPolicies(); // etc. }
Also, to ServiceReference:
public interface ServiceReference { ServiceInterface getInterface(); ServiceDomain getDomain(); ServiceSecurity getSecurity(); List<Policy> getRequiredPolicies(); List<Policy> getProvidedPolicies(); // etc. }
So, first question, are we okay with this API addition? Pretty please with a cherry on top?
Next, now that the ServiceSecurity is exposed at this level, inside my SecurityHandler, I get access to the correct ServiceSecurity based on metadata from the passed-in Exchange. What I can do is this:
public class SecurityHandler { public void handleMessage(Exchange exchange) throws HandlerException { ServiceSecurity serviceSecurity = exchange.getProvider().getSecurity(); // ...Use it, and do other stuff. e.g.: SecurityProvider.instance().authenticate(serviceSecurity, securityContext); } }
So, second question, when would I know to get the ServiceSecurity from the Service (provider) interface:
ServiceSecurity serviceSecurity = exchange.getProvider().getSecurity();
, and when would I know to get it from the ServiceReference (consumer) interface?:
ServiceSecurity serviceSecurity = exchange.getConsumer().getSecurity();
Thanks!