$inbound/ctx:transport/ctx:uri/text() will give you the proxy URI, that is /OSB_Project_1/Proxy_Service_1
$inbound contains this info:
<con:endpoint name="ProxyService$OSB Project 1$Proxy Service 1" xmlns:con="http://www.bea.com/wli/sb/context">
<con:service/>
<con:transport>
<con:uri>/OSB_Project_1/Proxy_Service_1</con:uri>
<con:mode>request-response</con:mode>
<con:qualityOfService>best-effort</con:qualityOfService>
<con:request xsi:type="http:HttpRequestMetaData" xmlns:http="http://www.bea.com/wli/sb/transports/http" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<tran:headers xsi:type="http:HttpRequestHeaders" xmlns:tran="http://www.bea.com/wli/sb/transports">
<http:Content-Type>text/xml; charset=utf-8</http:Content-Type>
</tran:headers>
<tran:encoding xmlns:tran="http://www.bea.com/wli/sb/transports">utf-8</tran:encoding>
</con:request>
<con:response xsi:type="http:HttpResponseMetaData" xmlns:http="http://www.bea.com/wli/sb/transports/http" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<tran:headers xsi:type="http:HttpResponseHeaders" xmlns:tran="http://www.bea.com/wli/sb/transports">
<http:Content-Type>text/xml</http:Content-Type>
</tran:headers>
<tran:response-code xmlns:tran="http://www.bea.com/wli/sb/transports">0</tran:response-code>
</con:response>
</con:transport>
<con:security>
<con:transportClient>
<con:username><anonymous></con:username>
</con:transportClient>
</con:security>
</con:endpoint>
Friday, April 30, 2010
Thursday, April 29, 2010
OSB sample code
thank you Oracle
http://www.oracle.com/technology/sample_code/products/osb/index.html
if the above fails, try this:
http://www.oracle.com/technetwork/middleware/service-bus/osbsamples-085201.html
particularly impressive is the one on Tuxedo
http://www.oracle.com/technology/obe/fusion_middleware/tuxedo/OSBTuxedoTransport/UsingOSBTuxedoTransport.htm
http://www.oracle.com/technology/sample_code/products/osb/index.html
if the above fails, try this:
http://www.oracle.com/technetwork/middleware/service-bus/osbsamples-085201.html
particularly impressive is the one on Tuxedo
http://www.oracle.com/technology/obe/fusion_middleware/tuxedo/OSBTuxedoTransport/UsingOSBTuxedoTransport.htm
Quick WLST script to setup JMS Server, Connection Factory and Queue
see also http://download.oracle.com/docs/cd/E13222_01/wls/docs91/config_scripting/using_WLST.html
setWLSEnv.cmd
java weblogic.WLST
execfile('myfile.py')
connect('weblogic', 'weblogic', 't3://localhost:7001')
startEdit()
cd('/')
cmo.createJMSSystemResource('ExceptionHandlingModule')
cd('/SystemResources/ExceptionHandlingModule')
set('Targets',jarray.array([ObjectName('com.bea:Name=AdminServer,Type=Server')], ObjectName))
cmo.createSubDeployment('acme.integration.ExceptionHandlingSubdeployment')
cd('/JMSSystemResources/ExceptionHandlingModule/JMSResource/ExceptionHandlingModule')
cmo.createConnectionFactory('acme.integration.QueueConnectionFactory')
cd('/JMSSystemResources/ExceptionHandlingModule/JMSResource/ExceptionHandlingModule/ConnectionFactories/acme.integration.QueueConnectionFactory')
cmo.setJNDIName('acme.integration.QueueConnectionFactory')
cd('/JMSSystemResources/ExceptionHandlingModule/JMSResource/ExceptionHandlingModule/ConnectionFactories/acme.integration.QueueConnectionFactory/SecurityParams/acme.integration.QueueConnectionFactory')
cmo.setAttachJMSXUserId(false)
cd('/SystemResources/ExceptionHandlingModule/SubDeployments/acme.integration.ExceptionHandlingSubdeployment')
set('Targets',jarray.array([], ObjectName))
cd('/JMSSystemResources/ExceptionHandlingModule/JMSResource/ExceptionHandlingModule/ConnectionFactories/acme.integration.QueueConnectionFactory')
cmo.setSubDeploymentName('acme.integration.ExceptionHandlingSubdeployment')
cd('/')
cmo.createFileStore('exceptionHandlingStore')
cd('/FileStores/exceptionHandlingStore')
set('Targets',jarray.array([ObjectName('com.bea:Name=AdminServer,Type=Server')], ObjectName))
cd('/')
cmo.createJMSServer('exceptionHandlingServer')
cd('/Deployments/exceptionHandlingServer')
cmo.setPersistentStore(getMBean('/FileStores/exceptionHandlingStore'))
set('Targets',jarray.array([ObjectName('com.bea:Name=AdminServer,Type=Server')], ObjectName))
cd('/SystemResources/ExceptionHandlingModule/SubDeployments/acme.integration.ExceptionHandlingSubdeployment')
set('Targets',jarray.array([ObjectName('com.bea:Name=exceptionHandlingServer,Type=JMSServer')], ObjectName))
cd('/JMSSystemResources/ExceptionHandlingModule/JMSResource/ExceptionHandlingModule')
cmo.createQueue('acme.integration.osbErrorQueue')
cd('/JMSSystemResources/ExceptionHandlingModule/JMSResource/ExceptionHandlingModule/Queues/acme.integration.osbErrorQueue')
cmo.setJNDIName('acme.integration.osbErrorQueue')
cmo.setSubDeploymentName('acme.integration.ExceptionHandlingSubdeployment')
cd('/SystemResources/ExceptionHandlingModule/SubDeployments/acme.integration.ExceptionHandlingSubdeployment')
set('Targets',jarray.array([ObjectName('com.bea:Name=exceptionHandlingServer,Type=JMSServer')], ObjectName))
activate()
Wednesday, April 28, 2010
XQuery tutorial: frequently used stuff
See here http://en.wikibooks.org/wiki/XQuery for a wealth of excellent examples.
Also http://www.xqueryfunctions.com/xq/ is wonderful.
XQuery is a terrible pain in the knee, but if you get organized it's only a matter of copying/pasting/hacking....
___________________
Variable substitution in a text:
xquery version "1.0" encoding "Cp1252";
(:: pragma type="xs:anyType" ::)
declare namespace xf = "http://tempuri.org/PVOSBProject1/XQExceptionHandling/";
declare function xf:XQExceptionHandling($thefault as xs:string)
as element(*) {
<ws:handleException xmlns:ws="http://com/pierre/ws">
<ws:fault>{$thefault}</ws:fault>
</ws:handleException>
};
declare variable $thefault as xs:string external;
xf:XQExceptionHandling($thefault)
___________________
if you want to pass any xml, use
declare variable $thefault as element(*) external;
______
if you callout a service expecting a String , you cannot pass an XML.... first you must fn-bea:serialize($thevariable)
the function fn:string($body) will somehow generate a toString() of your XML
_____________
Assume this is the $body:
<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<dbac:insertCompany xmlns:dbac="http://com/acme/dbaccess">
<dbac:company xmlns:java="java:com.acme.dbaccess">
<java:CreationDate>3</java:CreationDate>
<java:Id>2</java:Id>
<java:Name>Pluto</java:Name>
</dbac:company>
</dbac:insertCompany>
</soapenv:Body>
$body/. means all the body... equivalent to $body
$body/dbac:company returns this:
<dbac:company xmlns:java="java:com.acme.dbaccess" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dbac="http://com/acme/dbaccess">
<java:CreationDate>3</java:CreationDate>
<java:Id>2</java:Id>
<java:Name>Pluto</java:Name>
</dbac:company>
$body/*/node() also returns
<dbac:company xmlns:java="java:com.acme.dbaccess" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dbac="http://com/acme/dbaccess">
<java:CreationDate>3</java:CreationDate>
<java:Id>2</java:Id>
<java:Name>Pluto</java:Name>
</dbac:company>
(be careful: $body/node() is different from $body/*/node() )
$operation will contain insertCompany
$body/node() will return
<dbac:insertCompany xmlns:dbac="http://com/acme/dbaccess">
<dbac:company xmlns:java="java:com.acme.dbaccess">
<java:CreationDate>3</java:CreationDate>
<java:Id>2</java:Id>
<java:Name>Pluto</java:Name>
</dbac:company>
</dbac:insertCompany>
use the condition fn:compare($a, $b) = 0 to test equality of 2 strings
fn:name($body) will return dbac:insertCompany
fn:local-name($body) will return insertCompany
fn:node-name($body): {http://com/acme/dbaccess}insertCompany
___________
XQuery: converting nodes in a CSV list
I have this:
<getLocationsByLocationIds>
<string>string_1</string>
<string>string_2</string>
</getLocationsByLocationIds>
and I want to convert it into this:
string_1,string_2
use this:
fn:string-join( $body/getLocationsByLocationIds/string, ',')
___________
Also http://www.xqueryfunctions.com/xq/ is wonderful.
XQuery is a terrible pain in the knee, but if you get organized it's only a matter of copying/pasting/hacking....
___________________
Variable substitution in a text:
xquery version "1.0" encoding "Cp1252";
(:: pragma type="xs:anyType" ::)
declare namespace xf = "http://tempuri.org/PVOSBProject1/XQExceptionHandling/";
declare function xf:XQExceptionHandling($thefault as xs:string)
as element(*) {
<ws:handleException xmlns:ws="http://com/pierre/ws">
<ws:fault>{$thefault}</ws:fault>
</ws:handleException>
};
declare variable $thefault as xs:string external;
xf:XQExceptionHandling($thefault)
___________________
if you want to pass any xml, use
declare variable $thefault as element(*) external;
______
if you callout a service expecting a String , you cannot pass an XML.... first you must fn-bea:serialize($thevariable)
the function fn:string($body) will somehow generate a toString() of your XML
_____________
Assume this is the $body:
<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<dbac:insertCompany xmlns:dbac="http://com/acme/dbaccess">
<dbac:company xmlns:java="java:com.acme.dbaccess">
<java:CreationDate>3</java:CreationDate>
<java:Id>2</java:Id>
<java:Name>Pluto</java:Name>
</dbac:company>
</dbac:insertCompany>
</soapenv:Body>
$body/. means all the body... equivalent to $body
$body/dbac:company returns this:
<dbac:company xmlns:java="java:com.acme.dbaccess" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dbac="http://com/acme/dbaccess">
<java:CreationDate>3</java:CreationDate>
<java:Id>2</java:Id>
<java:Name>Pluto</java:Name>
</dbac:company>
$body/*/node() also returns
<dbac:company xmlns:java="java:com.acme.dbaccess" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:dbac="http://com/acme/dbaccess">
<java:CreationDate>3</java:CreationDate>
<java:Id>2</java:Id>
<java:Name>Pluto</java:Name>
</dbac:company>
(be careful: $body/node() is different from $body/*/node() )
$operation will contain insertCompany
$body/node() will return
<dbac:insertCompany xmlns:dbac="http://com/acme/dbaccess">
<dbac:company xmlns:java="java:com.acme.dbaccess">
<java:CreationDate>3</java:CreationDate>
<java:Id>2</java:Id>
<java:Name>Pluto</java:Name>
</dbac:company>
</dbac:insertCompany>
use the condition fn:compare($a, $b) = 0 to test equality of 2 strings
fn:name($body) will return dbac:insertCompany
fn:local-name($body) will return insertCompany
fn:node-name($body): {http://com/acme/dbaccess}insertCompany
___________
XQuery: converting nodes in a CSV list
I have this:
<getLocationsByLocationIds>
<string>string_1</string>
<string>string_2</string>
</getLocationsByLocationIds>
and I want to convert it into this:
string_1,string_2
use this:
fn:string-join( $body/getLocationsByLocationIds/string, ',')
___________
Labels:
XQuery
The way a Weblogic Web Service returns a Stacktrace in a SOAP Fault
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header />
<env:Body>
<env:Fault>
<faultcode>env:Server</faultcode>
<faultstring>Failed to invoke end component com.pierre.ws.PierreWS (POJO), operation=generateFault1
-> Failed to invoke method
-> ciao1
</faultstring>
<detail>
<bea_fault:stacktrace xmlns:bea_fault="http://www.bea.com/servers/wls70/webservice/fault/1.0.0">java.lang.Exception: ciao1
at com.pierre.ws.PierreWS.generateFault1(PierreWS.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at weblogic.wsee.component.pojo.JavaClassComponent.invoke(JavaClassComponent.java:112)
at weblogic.wsee.ws.dispatch.server.ComponentHandler.handleRequest(ComponentHandler.java:84)
at weblogic.wsee.handler.HandlerIterator.handleRequest(HandlerIterator.java:141)
at weblogic.wsee.ws.dispatch.server.ServerDispatcher.dispatch(ServerDispatcher.java:114)
at weblogic.wsee.ws.WsSkel.invoke(WsSkel.java:80)
at weblogic.wsee.server.servlet.SoapProcessor.handlePost(SoapProcessor.java:66)
at weblogic.wsee.server.servlet.SoapProcessor.process(SoapProcessor.java:44)
at weblogic.wsee.server.servlet.BaseWSServlet$AuthorizedInvoke.run(BaseWSServlet.java:285)
at weblogic.wsee.server.servlet.BaseWSServlet.service(BaseWSServlet.java:169)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3498)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(Unknown Source)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2180)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2086)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1406)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
</bea_fault:stacktrace>
</detail>
</env:Fault>
</env:Body>
</env:Envelope>
<env:Header />
<env:Body>
<env:Fault>
<faultcode>env:Server</faultcode>
<faultstring>Failed to invoke end component com.pierre.ws.PierreWS (POJO), operation=generateFault1
-> Failed to invoke method
-> ciao1
</faultstring>
<detail>
<bea_fault:stacktrace xmlns:bea_fault="http://www.bea.com/servers/wls70/webservice/fault/1.0.0">java.lang.Exception: ciao1
at com.pierre.ws.PierreWS.generateFault1(PierreWS.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at weblogic.wsee.component.pojo.JavaClassComponent.invoke(JavaClassComponent.java:112)
at weblogic.wsee.ws.dispatch.server.ComponentHandler.handleRequest(ComponentHandler.java:84)
at weblogic.wsee.handler.HandlerIterator.handleRequest(HandlerIterator.java:141)
at weblogic.wsee.ws.dispatch.server.ServerDispatcher.dispatch(ServerDispatcher.java:114)
at weblogic.wsee.ws.WsSkel.invoke(WsSkel.java:80)
at weblogic.wsee.server.servlet.SoapProcessor.handlePost(SoapProcessor.java:66)
at weblogic.wsee.server.servlet.SoapProcessor.process(SoapProcessor.java:44)
at weblogic.wsee.server.servlet.BaseWSServlet$AuthorizedInvoke.run(BaseWSServlet.java:285)
at weblogic.wsee.server.servlet.BaseWSServlet.service(BaseWSServlet.java:169)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3498)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(Unknown Source)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2180)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2086)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1406)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)
</bea_fault:stacktrace>
</detail>
</env:Fault>
</env:Body>
</env:Envelope>
Labels:
soap fault
OSB: difference between Route, Service Callout and Publish
service call out .. you call a service in a SYNCHRONOUS way (pipeline blocks and waits for service response)
publish ... same but ASYNCHRONOUS, so message flow continues in the pipeline
route ... it's the last node of the proxy, it's not in the pipeline, you pass all processing to another (business or proxy) service
publish ... same but ASYNCHRONOUS, so message flow continues in the pipeline
route ... it's the last node of the proxy, it's not in the pipeline, you pass all processing to another (business or proxy) service
Labels:
OSB
Tuesday, April 27, 2010
OSB faults transformed into SOAP 1.2 and SOAP 1.1 format
If the client that invokes OSB adheres to the SOAP 1.2 standard, you can always transform the OSB SOAP Fault into the 1.2 standard with this XQuery transformation:
declare namespace xf =
"http://tempuri.org/Transformations/transformations/transformCustomFaultToSoapFault/";
declare namespace soap = "http://www.w3.org/2003/05/soap-envelope";
declare namespace flt = "http://www.bea.com/wli/sb/context";
declare function xf:transformCustomFaultToSoapFault($fault1 as
element(flt:fault))
as element(soap:Fault) {
<soap:Fault>
<soap:Code>
<soap:Value>soap:Receiver</soap:Value>
</soap:Code>
<soap:Reason>
<soap:Text>{ concat(data($fault1/flt:errorCode) , "-"
, data($fault1/flt:reason)) }</soap:Text>
</soap:Reason>
{
for $location in $fault1/flt:location
let $node := data($location/flt:node)
let $pipeline := data($location/flt:pipeline)
let $stage := data($location/flt:stage)
let $error-handler := data($location/flt:error-handler)
let $path := data($location/flt:path)
return
<soap:Node>{ concat($node ,"-" , $pipeline ,"-" ,
$stage ,"-" , $error-handler ,"-" , $path) }</soap:Node>
}
{
for $details in $fault1/flt:details
return
<soap:Detail>{ $details/@* , $details/node() }</soap:Detail>
}
</soap:Fault>
};
declare variable $fault1 as element(flt:fault) external;
xf:transformCustomFaultToSoapFault($fault1)
And this is the SOAP 1.1 version:
declare namespace xf =
"http://tempuri.org/Transformations/transformations/transformCustomFaultToSoap11Fault/";
declare namespace ns0 = "http://schemas.xmlsoap.org/soap/envelope/";
declare namespace ns1 = "http://www.bea.com/wli/sb/context";
declare function xf:transformCustomFaultToSoap11Fault($fault1 as
element(ns1:fault))
as element(*) {
<ns0:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>{ concat($fault1/ns1:errorCode , "-"
,$fault1/ns1:reason) }</faultstring>
{
for $node in $fault1/ns1:location/ns1:node
let $error-handler := data($fault1/ns1:location/ns1:error-handler)
let $path := data($fault1/ns1:location/ns1:path)
let $stage := data($fault1/ns1:location/ns1:stage)
let $pipeline := data($fault1/ns1:location/ns1:pipeline)
return
<faultactor>{ concat($node , "-" , $error-handler , "-" ,
$path , "-" , $stage , "-" , $pipeline) }</faultactor>
}
{
for $details in $fault1/ns1:details
return
<detail>{ $details/@* , $details/node() }</detail>
}
</ns0:Fault>
};
declare variable $fault1 as element(ns1:fault) external;
xf:transformCustomFaultToSoap11Fault($fault1)
declare namespace xf =
"http://tempuri.org/Transformations/transformations/transformCustomFaultToSoapFault/";
declare namespace soap = "http://www.w3.org/2003/05/soap-envelope";
declare namespace flt = "http://www.bea.com/wli/sb/context";
declare function xf:transformCustomFaultToSoapFault($fault1 as
element(flt:fault))
as element(soap:Fault) {
<soap:Fault>
<soap:Code>
<soap:Value>soap:Receiver</soap:Value>
</soap:Code>
<soap:Reason>
<soap:Text>{ concat(data($fault1/flt:errorCode) , "-"
, data($fault1/flt:reason)) }</soap:Text>
</soap:Reason>
{
for $location in $fault1/flt:location
let $node := data($location/flt:node)
let $pipeline := data($location/flt:pipeline)
let $stage := data($location/flt:stage)
let $error-handler := data($location/flt:error-handler)
let $path := data($location/flt:path)
return
<soap:Node>{ concat($node ,"-" , $pipeline ,"-" ,
$stage ,"-" , $error-handler ,"-" , $path) }</soap:Node>
}
{
for $details in $fault1/flt:details
return
<soap:Detail>{ $details/@* , $details/node() }</soap:Detail>
}
</soap:Fault>
};
declare variable $fault1 as element(flt:fault) external;
xf:transformCustomFaultToSoapFault($fault1)
And this is the SOAP 1.1 version:
declare namespace xf =
"http://tempuri.org/Transformations/transformations/transformCustomFaultToSoap11Fault/";
declare namespace ns0 = "http://schemas.xmlsoap.org/soap/envelope/";
declare namespace ns1 = "http://www.bea.com/wli/sb/context";
declare function xf:transformCustomFaultToSoap11Fault($fault1 as
element(ns1:fault))
as element(*) {
<ns0:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>{ concat($fault1/ns1:errorCode , "-"
,$fault1/ns1:reason) }</faultstring>
{
for $node in $fault1/ns1:location/ns1:node
let $error-handler := data($fault1/ns1:location/ns1:error-handler)
let $path := data($fault1/ns1:location/ns1:path)
let $stage := data($fault1/ns1:location/ns1:stage)
let $pipeline := data($fault1/ns1:location/ns1:pipeline)
return
<faultactor>{ concat($node , "-" , $error-handler , "-" ,
$path , "-" , $stage , "-" , $pipeline) }</faultactor>
}
{
for $details in $fault1/ns1:details
return
<detail>{ $details/@* , $details/node() }</detail>
}
</ns0:Fault>
};
declare variable $fault1 as element(ns1:fault) external;
xf:transformCustomFaultToSoap11Fault($fault1)
Labels:
soap fault
OSB transport headers
<con:transport xmlns:con="http://www.bea.com/wli/sb/context">
<con:uri>/PVOSBProject1/PVTestFault01</con:uri>
<con:mode>request-response</con:mode>
<con:qualityOfService>best-effort</con:qualityOfService>
<con:request xsi:type="http:HttpRequestMetaData" xmlns:http="http://www.bea.com/wli/sb/transports/http" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<tran:headers xsi:type="http:HttpRequestHeaders" xmlns:tran="http://www.bea.com/wli/sb/transports">
<http:Content-Type>text/xml; charset=utf-8</http:Content-Type>
<http:SOAPAction>"generateFault2"</http:SOAPAction>
</tran:headers>
<tran:encoding xmlns:tran="http://www.bea.com/wli/sb/transports">utf-8</tran:encoding>
</con:request>
<con:response xsi:type="http:HttpResponseMetaData" xmlns:http="http://www.bea.com/wli/sb/transports/http" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<tran:headers xsi:type="http:HttpResponseHeaders" xmlns:tran="http://www.bea.com/wli/sb/transports">
<http:Content-Type>text/xml</http:Content-Type>
</tran:headers>
<tran:response-code xmlns:tran="http://www.bea.com/wli/sb/transports">0</tran:response-code>
</con:response>
</con:transport>
You can customize the tran:headers section with a tran:user-header with a custom header
<tran:headers xsi:type="http:HttpRequestHeaders" xmlns:tran="http://www.bea.com/wli/sb/transports">
<tran:user-header name="messageHistory" value="ciaobellagioia"/>
<http:Content-Type>text/xml; charset=utf-8</http:Content-Type>
this is how I added the header:
This way the Caller Proxy Service sets the header on the $outbound variable. The Called Proxy Service MUST be set with the option "GET ALL HEADERS" in the "Transport" tab, otherwise the transport header will be lost. Or, at least, add the "messageHistory" in the list of headers to be explicitly copied.
The Called Proxy Service will get the header in the $inbound variable, transport section.
OF COURSE you whould not put messageHistory in a transport header, the right place is in the SOAP header. Don't confuse TRANSPORT HEADER with SOAP HEADER.
<con:uri>/PVOSBProject1/PVTestFault01</con:uri>
<con:mode>request-response</con:mode>
<con:qualityOfService>best-effort</con:qualityOfService>
<con:request xsi:type="http:HttpRequestMetaData" xmlns:http="http://www.bea.com/wli/sb/transports/http" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<tran:headers xsi:type="http:HttpRequestHeaders" xmlns:tran="http://www.bea.com/wli/sb/transports">
<http:Content-Type>text/xml; charset=utf-8</http:Content-Type>
<http:SOAPAction>"generateFault2"</http:SOAPAction>
</tran:headers>
<tran:encoding xmlns:tran="http://www.bea.com/wli/sb/transports">utf-8</tran:encoding>
</con:request>
<con:response xsi:type="http:HttpResponseMetaData" xmlns:http="http://www.bea.com/wli/sb/transports/http" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<tran:headers xsi:type="http:HttpResponseHeaders" xmlns:tran="http://www.bea.com/wli/sb/transports">
<http:Content-Type>text/xml</http:Content-Type>
</tran:headers>
<tran:response-code xmlns:tran="http://www.bea.com/wli/sb/transports">0</tran:response-code>
</con:response>
</con:transport>
You can customize the tran:headers section with a tran:user-header with a custom header
<tran:headers xsi:type="http:HttpRequestHeaders" xmlns:tran="http://www.bea.com/wli/sb/transports">
<tran:user-header name="messageHistory" value="ciaobellagioia"/>
<http:Content-Type>text/xml; charset=utf-8</http:Content-Type>
this is how I added the header:
This way the Caller Proxy Service sets the header on the $outbound variable. The Called Proxy Service MUST be set with the option "GET ALL HEADERS" in the "Transport" tab, otherwise the transport header will be lost. Or, at least, add the "messageHistory" in the list of headers to be explicitly copied.
The Called Proxy Service will get the header in the $inbound variable, transport section.
OF COURSE you whould not put messageHistory in a transport header, the right place is in the SOAP header. Don't confuse TRANSPORT HEADER with SOAP HEADER.
Labels:
osbtransport
Monday, April 26, 2010
SOAP Fault in OSB
see also http://www.javamonamour.org/2010/07/osb-error-handling-fault.html
this is what the WS method does:
@WebMethod(action="generateFault1")
public void generateFault1() throws Exception {
throw new Exception("ciao1");
}
and this is what the method generates when run in OSB
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Server</faultcode>
<faultstring>BEA-380001: Internal Server Error</faultstring>
<detail>
<con:fault xmlns:con="http://www.bea.com/wli/sb/context">
<con:errorCode>BEA-380001</con:errorCode>
<con:reason>Internal Server Error</con:reason>
<con:location>
<con:node>RouteTo_BSPVWS01</con:node>
<con:path>response-pipeline</con:path>
</con:location>
</con:fault>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
This is the structure of the fault element
This is how to declare the faults generated by an operation:
http://www.w3.org/TR/wsdl#_soap:fault
here in more details
http://docs.sun.com/app/docs/doc/821-0015/ggeip2?a=view
A really interesting article defining Business Faults versus System Faults, and Fault handling Policies
http://www.troubleshootingwiki.org/Handling_errors_in_SOA_based_systems
nothing new really, in the Java world there are the same concepts, much better defined.
The fascinating thing is that in the Error Handler you have all sort of information disseminated in 2 places: the $fault variable and the $body variable
$fault: <con:fault xmlns:con="http://www.bea.com/wli/sb/context">
<con:errorCode>BEA-380001</con:errorCode>
<con:reason>Internal Server Error</con:reason>
<con:location>
<con:node>RouteNode1</con:node>
<con:path>response-pipeline</con:path>
</con:location>
</con:fault>>
$body: <env:Body xmlns:
env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Fault>
<faultcode>env:Server</faultcode>
<faultstring>ciao2</faultstring>
<detail>
<java:PierreException xmlns:java="java:com.pierre.exceptions"/>
</detail>
</env:Fault>
</env:Body>>
(the exception being thrown is new com.pierre.exceptions.PierreException("ciao2")
The complete stacktrace is missing though...
this is what the WS method does:
@WebMethod(action="generateFault1")
public void generateFault1() throws Exception {
throw new Exception("ciao1");
}
and this is what the method generates when run in OSB
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Server</faultcode>
<faultstring>BEA-380001: Internal Server Error</faultstring>
<detail>
<con:fault xmlns:con="http://www.bea.com/wli/sb/context">
<con:errorCode>BEA-380001</con:errorCode>
<con:reason>Internal Server Error</con:reason>
<con:location>
<con:node>RouteTo_BSPVWS01</con:node>
<con:path>response-pipeline</con:path>
</con:location>
</con:fault>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
This is the structure of the fault element
This is how to declare the faults generated by an operation:
http://www.w3.org/TR/wsdl#_soap:fault
here in more details
http://docs.sun.com/app/docs/doc/821-0015/ggeip2?a=view
A really interesting article defining Business Faults versus System Faults, and Fault handling Policies
http://www.troubleshootingwiki.org/Handling_errors_in_SOA_based_systems
nothing new really, in the Java world there are the same concepts, much better defined.
The fascinating thing is that in the Error Handler you have all sort of information disseminated in 2 places: the $fault variable and the $body variable
$fault: <con:fault xmlns:con="http://www.bea.com/wli/sb/context">
<con:errorCode>BEA-380001</con:errorCode>
<con:reason>Internal Server Error</con:reason>
<con:location>
<con:node>RouteNode1</con:node>
<con:path>response-pipeline</con:path>
</con:location>
</con:fault>>
$body: <env:Body xmlns:
env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Fault>
<faultcode>env:Server</faultcode>
<faultstring>ciao2</faultstring>
<detail>
<java:PierreException xmlns:java="java:com.pierre.exceptions"/>
</detail>
</env:Fault>
</env:Body>>
(the exception being thrown is new com.pierre.exceptions.PierreException("ciao2")
The complete stacktrace is missing though...
Labels:
OSB,
soap fault
Friday, April 23, 2010
SOAP or REST? Which is the BEST?
An interesting article examining REST features
https://www.ibm.com/developerworks/webservices/library/ws-restful/
and a good introduction to REST
http://www.ibm.com/developerworks/webservices/library/wa-jaxrs/index.html
more later....
https://www.ibm.com/developerworks/webservices/library/ws-restful/
and a good introduction to REST
http://www.ibm.com/developerworks/webservices/library/wa-jaxrs/index.html
more later....
Labels:
REST
Sunday, April 11, 2010
SOAP messages patterns
a useful collection of SOAP message patterns:
http://www.w3.org/TR/xmlp-scenarios/
a message for all seasons....
Especially interesting:
http://www.w3.org/TR/xmlp-scenarios/#S807
<n:MessageId>uuid:09233523-567b-2891-b623-9dke28yod7m9</n:MessageId>
<n:ResponseTo>uuid:09233523-345b-4351-b623-5dsf35sgs5d6</n:ResponseTo>
</n:MsgHeader>
http://www.w3.org/TR/xmlp-scenarios/
a message for all seasons....
Especially interesting:
http://www.w3.org/TR/xmlp-scenarios/#S807
TrackingHeader with Via Intermediary with Timestamp
(excellent for troubleshooting and performance monitoring!)
<t:TrackingHeader xmlns:t="http://example.org/2001/06/tracking"> <t:Via> <t:Intermediary>soap://A.com/some/endpoint</t:Intermediary> <t:Timestamp>2001-03-09T08:00:00Z</t:Timestamp> </t:Via>
and the response correlated to the messageId<n:MsgHeader xmlns:n="http://example.org/requestresponse">
<n:MessageId>uuid:09233523-567b-2891-b623-9dke28yod7m9</n:MessageId>
<n:ResponseTo>uuid:09233523-345b-4351-b623-5dsf35sgs5d6</n:ResponseTo>
</n:MsgHeader>
Labels:
SOAP
Wednesday, April 7, 2010
More on WLI and UsernameToken
if you provide this policy file to protect your WLI process:
@WSSecurityService(file="mypolicy.xml")
<wssecuritypolicy xsi:schemalocation="WSSecurity-policy.xsd">
xmlns="http://www.bea.com/2003/03/wsse/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<wssecurityin>
<token tokentype="username">
</token></wssecurityin></wssecuritypolicy>
you get this error message:
java.rmi.RemoteException: EJB Exception: ; nested exception is:
com.bea.wli.knex.runtime.jws.wssecurity.exception.WLWWSSEException: Policy requires Message to contain UsernameToken, UsernameToken not found in the Message.
Caused by: com.bea.wli.knex.runtime.jws.wssecurity.exception.WLWWSSEException: Policy requires Message to contain UsernameToken, UsernameToken not found in the Message.
this is fantastic. I wonder why WLI manuals say that JPD don't support security... they are funny.
Now I try passing a Username in the Soap Header:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:open="http://www.openuri.org/">
<soapenv:Header>
<wsse:Security
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
soapenv:mustUnderstand="1">
<wsse:UsernameToken wsu:Id="SecurityToken-1">
<wsse:Username>username</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
password
</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<open:clientRequestwithReturn>
<!--Optional:-->
<open:x0>pippo</open:x0>
</open:clientRequestwithReturn>
</soapenv:Body>
</soapenv:Envelope>
and I get a fantastic:
javax.security.auth.login.FailedLoginException: [Security:090304]Authentication Failed: User username at weblogic.security.providers.authentication.LDAPAtnLoginModuleImpl.login(LDAPAtnLoginModuleImpl.java:230)
at com.bea.common.security.internal.service.LoginModuleWrapper$1.run(LoginModuleWrapper.java:110)
at com.bea.common.security.internal.service.LoginModuleWrapper.login(LoginModuleWrapper.java:106)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
at javax.security.auth.login.LoginContext.login(LoginContext.java:579)
at com.bea.common.security.internal.service.JAASLoginServiceImpl.login(JAASLoginServiceImpl.java:113)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.bea.common.security.internal.utils.Delegator$ProxyInvocationHandler.invoke(Delegator.java:57)
at $Proxy16.login(Unknown Source)
at weblogic.security.service.internal.WLSJAASLoginServiceImpl$ServiceImpl.login(Unknown Source)
at com.bea.common.security.internal.service.JAASAuthenticationServiceImpl.authenticate(JAASAuthenticationServiceImpl.java:82)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.bea.common.security.internal.utils.Delegator$ProxyInvocationHandler.invoke(Delegator.java:57)
at $Proxy34.authenticate(Unknown Source)
at weblogic.security.service.WLSJAASAuthenticationServiceWrapper.authenticate(Unknown Source)
at weblogic.security.service.PrincipalAuthenticator.authenticate(Unknown Source)
at weblogic.security.service.PrincipalAuthenticator.authenticate(Unknown Source)
at weblogic.webservice.util.ServerSecurityHelper.assertIdentity(ServerSecurityHelper.java:45)
at com.bea.wli.knex.runtime.jws.wssecurity.inbound.WLWInboundWSSEImpl.assertIdentity(WLWInboundWSSEImpl.java:458)
Exciting!
I can see in the stacktrace interesting stuff like: ServerSecurityHelper.assertIdentity(), PrincipalAuthenticator.authenticate(), JAASAuthenticationServiceImpl.authenticate(), LDAPAtnLoginModuleImpl.login()...
Now I create the username "username" in the default security realm, with password "anotherpassword"
I still get the
javax.security.auth.login.FailedLoginException: [Security:090302]Authentication Failed: User username denied
(so we understand that "User xxx denied" could also mean "bad password")
When I provide the right password, everything works.
I am using SOAPUI to submit the request.
If I remove the Security header from the SOAP message, and I select the WSS-Password Type= password text, and I provide username and password in the appropriate properties, things work again fine. (tip: look in the SOAPUI http log, you should see the password being trasmitted in the clear with the SOAP request).
If you choose WSS-Password Type=digest, you transmit this:
<soapenv:Envelope xmlns:open="http://www.openuri.org/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header><wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:UsernameToken wsu:Id="UsernameToken-5" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><wsse:Username>username</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">DNBu/78N8l0BgBzKPvJglF8zlqw=</wsse:Password><wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">Kb64xrWI9XLLjdmTcIZATQ==</wsse:Nonce><wsu:Created>2010-04-07T12:27:21.353Z</wsu:Created></wsse:UsernameToken></wsse:Security></soapenv:Header>[\n]"
As recommended by OASIS http://www.oasis-open.org/committees/wss/documents/WSS-Username-02-0223-merged.pdf , also Nonce and Timestamp ("Created") are supplied (they are supplied also in the "password text" case).
Now, just for fun I hack the header and set Created to 2009-04-07T12:33:17.551Z
The Web Service still process it.... how to tell Web Service to reject a request which is 1 year old?
I look into http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/ws-securitypolicy.xsd if there is any such option. I don't see anything inspiring.
Theoretically the "Created" info should be embedded into a wsu:Timestamp element.... the WS-Security specs seem very loose and fuzzy, I have the impression that SOA is built on a under-specified standard which imposes every solution to reinvent the wheel adapting a generic standard to its own internal needs.
I guess some billion dollars have been lost so far because of this fuzziness.
Anyway... this is the standard:
<wsse:Security xmlns:wsse="..." xmlns:wsu="..."
soapenv:mustUnderstand="1">
<wsu:Timestamp wsu:Id="Timestamp-31497800">
<wsu:Created>2009-11-02T14:00:00Z</wsu:Created>
<wsu:Expires>2009-11-02T15:00:00Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken wsu:Id="UsernameToken-10697954">
<wsse:Username>...</wsse:Username>
<wsse:Password Type="...#PasswordText">...</wsse:Password>
</wsse:UsernameToken>
so the "created" is associated to the Timestamp, not to the Username... in fact I have read that the "Created" clause can be attached to any Element.
@WSSecurityService(file="mypolicy.xml")
<wssecuritypolicy xsi:schemalocation="WSSecurity-policy.xsd">
xmlns="http://www.bea.com/2003/03/wsse/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<wssecurityin>
<token tokentype="username">
</token></wssecurityin></wssecuritypolicy>
you get this error message:
java.rmi.RemoteException: EJB Exception: ; nested exception is:
com.bea.wli.knex.runtime.jws.wssecurity.exception.WLWWSSEException: Policy requires Message to contain UsernameToken, UsernameToken not found in the Message.
Caused by: com.bea.wli.knex.runtime.jws.wssecurity.exception.WLWWSSEException: Policy requires Message to contain UsernameToken, UsernameToken not found in the Message.
this is fantastic. I wonder why WLI manuals say that JPD don't support security... they are funny.
Now I try passing a Username in the Soap Header:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:open="http://www.openuri.org/">
<soapenv:Header>
<wsse:Security
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
soapenv:mustUnderstand="1">
<wsse:UsernameToken wsu:Id="SecurityToken-1">
<wsse:Username>username</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
password
</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<open:clientRequestwithReturn>
<!--Optional:-->
<open:x0>pippo</open:x0>
</open:clientRequestwithReturn>
</soapenv:Body>
</soapenv:Envelope>
and I get a fantastic:
javax.security.auth.login.FailedLoginException: [Security:090304]Authentication Failed: User username at weblogic.security.providers.authentication.LDAPAtnLoginModuleImpl.login(LDAPAtnLoginModuleImpl.java:230)
at com.bea.common.security.internal.service.LoginModuleWrapper$1.run(LoginModuleWrapper.java:110)
at com.bea.common.security.internal.service.LoginModuleWrapper.login(LoginModuleWrapper.java:106)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
at javax.security.auth.login.LoginContext.login(LoginContext.java:579)
at com.bea.common.security.internal.service.JAASLoginServiceImpl.login(JAASLoginServiceImpl.java:113)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.bea.common.security.internal.utils.Delegator$ProxyInvocationHandler.invoke(Delegator.java:57)
at $Proxy16.login(Unknown Source)
at weblogic.security.service.internal.WLSJAASLoginServiceImpl$ServiceImpl.login(Unknown Source)
at com.bea.common.security.internal.service.JAASAuthenticationServiceImpl.authenticate(JAASAuthenticationServiceImpl.java:82)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.bea.common.security.internal.utils.Delegator$ProxyInvocationHandler.invoke(Delegator.java:57)
at $Proxy34.authenticate(Unknown Source)
at weblogic.security.service.WLSJAASAuthenticationServiceWrapper.authenticate(Unknown Source)
at weblogic.security.service.PrincipalAuthenticator.authenticate(Unknown Source)
at weblogic.security.service.PrincipalAuthenticator.authenticate(Unknown Source)
at weblogic.webservice.util.ServerSecurityHelper.assertIdentity(ServerSecurityHelper.java:45)
at com.bea.wli.knex.runtime.jws.wssecurity.inbound.WLWInboundWSSEImpl.assertIdentity(WLWInboundWSSEImpl.java:458)
Exciting!
I can see in the stacktrace interesting stuff like: ServerSecurityHelper.assertIdentity(), PrincipalAuthenticator.authenticate(), JAASAuthenticationServiceImpl.authenticate(), LDAPAtnLoginModuleImpl.login()...
Now I create the username "username" in the default security realm, with password "anotherpassword"
I still get the
javax.security.auth.login.FailedLoginException: [Security:090302]Authentication Failed: User username denied
(so we understand that "User xxx denied" could also mean "bad password")
When I provide the right password, everything works.
I am using SOAPUI to submit the request.
If I remove the Security header from the SOAP message, and I select the WSS-Password Type= password text, and I provide username and password in the appropriate properties, things work again fine. (tip: look in the SOAPUI http log, you should see the password being trasmitted in the clear with the SOAP request).
If you choose WSS-Password Type=digest, you transmit this:
<soapenv:Envelope xmlns:open="http://www.openuri.org/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header><wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:UsernameToken wsu:Id="UsernameToken-5" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><wsse:Username>username</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">DNBu/78N8l0BgBzKPvJglF8zlqw=</wsse:Password><wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">Kb64xrWI9XLLjdmTcIZATQ==</wsse:Nonce><wsu:Created>2010-04-07T12:27:21.353Z</wsu:Created></wsse:UsernameToken></wsse:Security></soapenv:Header>[\n]"
As recommended by OASIS http://www.oasis-open.org/committees/wss/documents/WSS-Username-02-0223-merged.pdf , also Nonce and Timestamp ("Created") are supplied (they are supplied also in the "password text" case).
Now, just for fun I hack the header and set Created to 2009-04-07T12:33:17.551Z
The Web Service still process it.... how to tell Web Service to reject a request which is 1 year old?
I look into http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/ws-securitypolicy.xsd if there is any such option. I don't see anything inspiring.
Theoretically the "Created" info should be embedded into a wsu:Timestamp element.... the WS-Security specs seem very loose and fuzzy, I have the impression that SOA is built on a under-specified standard which imposes every solution to reinvent the wheel adapting a generic standard to its own internal needs.
I guess some billion dollars have been lost so far because of this fuzziness.
Anyway... this is the standard:
<wsse:Security xmlns:wsse="..." xmlns:wsu="..."
soapenv:mustUnderstand="1">
<wsu:Timestamp wsu:Id="Timestamp-31497800">
<wsu:Created>2009-11-02T14:00:00Z</wsu:Created>
<wsu:Expires>2009-11-02T15:00:00Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken wsu:Id="UsernameToken-10697954">
<wsse:Username>...</wsse:Username>
<wsse:Password Type="...#PasswordText">...</wsse:Password>
</wsse:UsernameToken>
so the "created" is associated to the Timestamp, not to the Username... in fact I have read that the "Created" clause can be attached to any Element.
WLDF in action
This is a REALLY interesting article on how to setup SNMP alerts in WebLogic, using the WLDF framework
http://www.oracle.com/technetwork/articles/cico-wldf-091073.html
It's POWERFUL. One wonders why people don't use WLDF and SNMP by default to manage WebLogic domains.
The answer is probably that these products are not properly packaged for the end user, they are still cumbersome to setup and exploit... so people still rely on 3rd party agents and monitoring tools like Nagios, Hyperic etc.
It's a pity that such a valuable tool receives so little attention.
http://www.oracle.com/technetwork/articles/cico-wldf-091073.html
It's POWERFUL. One wonders why people don't use WLDF and SNMP by default to manage WebLogic domains.
The answer is probably that these products are not properly packaged for the end user, they are still cumbersome to setup and exploit... so people still rely on 3rd party agents and monitoring tools like Nagios, Hyperic etc.
It's a pity that such a valuable tool receives so little attention.
Sunday, April 4, 2010
Good old Username Token authentication model for Web Services
Some practical documentation here:
http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/cwbs_usernametokenv6.html
and also an interesting podcast here
http://channel9.msdn.com/shows/ARCast+with+Ron+Jacobs/ARCast-Securing-Web-Services-with-the-Username-Token-in-WSE-30-Part-1/
on X509 PKI certificate and Username Token.
In a nutshell:
Kerberos and X509 are brokered authentication, you present a token which vouches that you have gone somewhere else through an authentication process
Username Token is direct authentication
A X509 contains a certificate which has a public key that can be used by the recipient to encrypt messages that can be only decrypted by the X509 originator.
The official OASIS documentation (interesting reading)
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf
An example of SOAP request with unencrypted Username token (thanks Tom Gullo, http://www.jroller.com/tgullo/, god bless your excellent recipes)
http://www.jroller.com/tgullo/resource/UsernamePasswordRequest.xml.txt
and encoded
http://www.jroller.com/tgullo/resource/EncryptedUsernamePasswordRequest.xml.txt
(it's really verbose, oh my god, I wonder about the performance impact)
http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/cwbs_usernametokenv6.html
and also an interesting podcast here
http://channel9.msdn.com/shows/ARCast+with+Ron+Jacobs/ARCast-Securing-Web-Services-with-the-Username-Token-in-WSE-30-Part-1/
on X509 PKI certificate and Username Token.
In a nutshell:
Kerberos and X509 are brokered authentication, you present a token which vouches that you have gone somewhere else through an authentication process
Username Token is direct authentication
A X509 contains a certificate which has a public key that can be used by the recipient to encrypt messages that can be only decrypted by the X509 originator.
The official OASIS documentation (interesting reading)
http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0.pdf
An example of SOAP request with unencrypted Username token (thanks Tom Gullo, http://www.jroller.com/tgullo/, god bless your excellent recipes)
http://www.jroller.com/tgullo/resource/UsernamePasswordRequest.xml.txt
and encoded
http://www.jroller.com/tgullo/resource/EncryptedUsernamePasswordRequest.xml.txt
(it's really verbose, oh my god, I wonder about the performance impact)
Labels:
usernametoken,
ws-security
Thursday, April 1, 2010
Penetration Tests and the Holy Grail of Security
I am reading this interesting document
http://www.owasp.org/images/5/56/OWASP_Testing_Guide_v3.pdf
provided by OWASP http://www.owasp.org , an "open source" security organization.
The dream was to find an intelligent PENETRATION (gasp!) test tool that find for you the security weaknesses of a Web Application (including Web Services).
See also http://en.wikipedia.org/wiki/Penetration_testing .
Anyway to quote the already quoted Gary McGraw,
“If you fail a penetration test you know you have a very bad problem indeed. If you pass a penetration test you do not know that you don’t have a very bad problem".
So, don't think that you are not PENETRABLE only because an AUTOMATED TOOL cannot PENETRATE you. Sorry but all this PENETRATION talks make me laugh. I am just Italian.
We shall cover later how to TEST your SECURITY. For a start never bend to pick up object that you dropped hahaha.
http://www.owasp.org/images/5/56/OWASP_Testing_Guide_v3.pdf
provided by OWASP http://www.owasp.org , an "open source" security organization.
The dream was to find an intelligent PENETRATION (gasp!) test tool that find for you the security weaknesses of a Web Application (including Web Services).
See also http://en.wikipedia.org/wiki/Penetration_testing .
Anyway to quote the already quoted Gary McGraw,
“If you fail a penetration test you know you have a very bad problem indeed. If you pass a penetration test you do not know that you don’t have a very bad problem".
So, don't think that you are not PENETRABLE only because an AUTOMATED TOOL cannot PENETRATE you. Sorry but all this PENETRATION talks make me laugh. I am just Italian.
We shall cover later how to TEST your SECURITY. For a start never bend to pick up object that you dropped hahaha.
Labels:
penetration
Subscribe to:
Posts (Atom)