7 Replies Latest reply on May 7, 2013 12:03 PM by dward

    Exposing service-level security meta-information

    dward

      The 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!

        • 1. Re: Exposing service-level security meta-information
          dward

          FYI, most of this is already implemented here: https://github.com/errantepiphany/switchyard-core/tree/SWITCHYARD-1414

          • 2. Re: Exposing service-level security meta-information
            dward

            Also FYI, here is what the ServiceSecurity interface looks like:

             

            public interface ServiceSecurity {

                public String getName();

                public Class<?> getCallbackHandler();

                public Map<String,String> getProperties();

                public Set<String> getRolesAllowed();

                public String getRunAs();

                public String getSecurityDomainName();

            }

             

            You can see it's read-only information.

            • 3. Re: Exposing service-level security meta-information
              kcbabo

              Config model looks good to me.

               

              I think the API hook in Service and ServiceReference should return a security provider name and not the interface.

               

              I think ServiceSecurity (or maybe SecurityProvider?) should be in runtime and ServiceDomain should have a method called something like:

              SecurityProvider getSecurityProvider(String name);

               

              This allows you to get at it directly from ServiceDomain and indirectly from Service and ServiceReference.

               

              Depending on the context, the provider name will be specified as part of the Service or ServiceReference.  Can you think of a scenario where it can be specified on both?  I'm not coming up with anything off the top of my head.  Even if there is a case, I think we can simplify things by saying that if both specify a provider name it must be the same.  We should add a check in the deployer to enforce this constraint.  This simplifies the provider lookup logic to simply check for a non-null provider name on the Service and ServiceReference used in an exchange.

              • 4. Re: Exposing service-level security meta-information
                splatch

                Looks good for me!

                • 5. Re: Exposing service-level security meta-information
                  dward
                  1. I am okay with Service and ServiceReference just returning a name, and accessing the interface with that name from the ServiceDomain. That makes sense.
                  2. There is a difference between ServiceSecurity and SecurityProvider. The first is the contract, and the second is the enforcer/validator. Maybe I might rename it to SecurityContract to make this more apparent. Dunno... But basically, the provider is given two arguments for anything it does: the contract, and the context that gets tested against it.
                  3. Yeah the non-null security(contract) name also makes sense when looking it up.

                   

                  Thanks!

                  • 6. Re: Exposing service-level security meta-information
                    kcbabo

                    The thing with #2 from my POV is that it's pointing to an instance of a security configuration.  I view the actual security policy requirements as the security "contract".  These policy requirements are mapped to an instance of a configuration to provide the realization of a security policy at runtime.

                    • 7. Re: Exposing service-level security meta-information
                      dward

                      Yeah, I came to that conclusion myself while coding, as I didn't like that name suffix either for the same reason.