How to implement Kerberos authentication to a SOAP Web Service using Teiid

Version 5

    In this usecase I have a SOAP web service that is secured through Kerberos.  Now I need to access this web service from Teiid.

     

    I will show how to do this for a non-SSO re-authentication scenario in this article. For when Teiid is already secured using Kerberos and the authentication is delegated via a Kerberos token to the back end SOAP web-service, see How to implement kerberos "delegation" based authentication to a SOAP Web Service using Teiid

     

    Basic knowledge of Teiid and JBoss EAP is assumed throughout this article.

     

    Step 1: Create a SOAP Web Service

    In this article, How to implement a SOAP Web Service with Kerberos authentication in JBoss EAP I showed an sample to create SOAP web-service. Please follow this article and create a sample web service, and test to make sure it works!

    If you are working with a third party web-service then gather the WSDL file for it, and make sure the service is operational and accessible.

     

    Step 2: Create VDB

    Now we need to create the VDB and required data sources to be consumed by the VDB. For my sample I used the following VDB (See Note about using Designer based VDB at the end of the article)

     

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <vdb name="kerberos" version="1">
    
        <description>Shows how to call SOAP Web with Kerberos Auth</description>
        <property name="cache-metadata" value="true"/>
    
        <model name="web">
            <source name="web" translator-name="ws" connection-jndi-name="java:/wsDS"/>  
       </model>
    
    </vdb>
    
    
    
    
    
    

     

    Step 3: Create Data Source

     

    Add the following xml fragment to resource-adapters subsystem in standalone-teiid.xml file. Note that the below configuration is setup for the sample service from step (1) when deployed in the same JBoss EAP. If your service is remote and/or different adjust the properties accordingly.

     

    <resource-adapter id="KerberosService">
        <module slot="main" id="org.jboss.teiid.resource-adapter.webservice"/>
        <transaction-support>NoTransaction</transaction-support>
        <connection-definitions>
            <connection-definition class-name="org.teiid.resource.adapter.ws.WSManagedConnectionFactory" jndi-name="java:/wsDS" enabled="true" use-java-context="true" pool-name="teiid-ws-ds">
                <config-property name="NamespaceUri">
                    http://webservices.samples.jboss.org/
                </config-property>
                <config-property name="ConfigFile">
                    /path/to/alice-cxf.xml
                </config-property>
                <config-property name="ServiceName">
                    HelloWorldService
                </config-property>
                <config-property name="Wsdl">
                    http://localhost:8080/kerberos/HelloWorld?wsdl
                </config-property>
                <config-property name="ConfigName">
                    HelloWorldPort
                </config-property>
                <config-property name="SecurityType">
                    WSSecurity
                </config-property>
                <config-property name="EndPoint">
                    http://localhost:8080/kerberos/HelloWorld
                </config-property>
            </connection-definition>
        </connection-definitions>
    </resource-adapter>
    
    
    
    
    
    

     

    Also add following to the "security-domains" subsystem:

     

    <security-domain name="alice" cache-type="default">
        <authentication>
            <login-module code="Kerberos" flag="required">
                <module-option name="storeKey" value="true"/>
                <module-option name="useKeyTab" value="true"/>
                <module-option name="keyTab" value="/path/to/alice.keytab"/>
                <module-option name="principal" value="alice@EXAMPLE.COM"/>
                <module-option name="doNotPrompt" value="true"/>
                <module-option name="debug" value="true"/>
                <module-option name="refreshKrb5Config" value="true"/>
            </login-module>
        </authentication>
    </security-domain>
    
    
    
    
    
    

     

    We also need alice-cxf.xml file above, the contents look like. Note again, the below should represent your service!

     

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:http="http://cxf.apache.org/transports/http/configuration"
        xmlns:jaxws="http://cxf.apache.org/jaxws"
        xmlns:cxf="http://cxf.apache.org/core"
        xmlns:p="http://cxf.apache.org/policy"
        xmlns:sec="http://cxf.apache.org/configuration/security"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
            http://cxf.apache.org/transports/http/configuration http://cxf.apache.org/schemas/configuration/http-conf.xsd
            http://cxf.apache.org/configuration/security http://cxf.apache.org/schemas/configuration/security.xsd
            http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd http://cxf.apache.org/policy http://cxf.apache.org/schemas/policy.xsd">
        <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
        <cxf:bus>
            <cxf:features>
                <p:policies/>
                <cxf:logging/>
            </cxf:features>
        </cxf:bus>
    
        <jaxws:client name="{http://webservices.samples.jboss.org/}HelloWorldPort" createdFromAPI="true">
            <jaxws:properties>
                <entry key="ws-security.kerberos.client">
                    <bean class="org.apache.cxf.ws.security.kerberos.KerberosClient">
                        <constructor-arg ref="cxf"/>
                        <property name="contextName" value="alice"/>
                        <property name="serviceName" value="bob@service.example.com"/>
                    </bean>
                </entry>
            </jaxws:properties>
        </jaxws:client>
    </beans>
    
    
    
    
    
    

     

    Step 4: Configure JDBC

     

    Using a JDBC client issue a query like ( you need to execute using java client as procedure, you can even write view then you can simply issue a select * from view)

     

    {?=call PM3.sayHello(XMLPARSE(DOCUMENT '<web:sayHello xmlns:web=\"http://webservices.samples.jboss.org/\"><arg0>hi</arg0></web:sayHello>'))}
    
    
    
    
    
    

     

    You will see out put like:

     

    <?xml version='1.0' encoding='UTF-8'?><return>Hello = hi From User = alice@EXAMPLE.COM</return>
    
    
    
    
    
    

     

    That is data from the web service created in the Step 1, also shows the connected user.

     

    Hopefully above showed you how to configure Teiid to issue Kerberos based SOAP call.

     

    Note: If you designed your VDB using the WSDL importer the above may not work as is, as Designer as of 8.7 version uses "invoke" method for executing the web service. If you want to use Designer, design the the VDB using WSDL importer, then use Teiid Connection importer and supply WSDL name and import the metadata from "ws" translator. Then switch the ws source model to this newly created model. Then edit all the transformations and edit them and replace "invoke" method with actual procedure name from source models. Note that the request XML is same in both. So, trim the verbose parameters and it should be good. Added [TEIIDDES-2371] WSDL Based procedure metadata needs to be used - JBoss Issue Tracker to fix the issue.


    Thanks for reading.


    Ramesh..