Tuesday, November 3, 2009

WebLogic Server (WLS) to Oracle Service Bus (OSB) to WebLogic Server using SAML Sender Vouches

I'm sure many people were hoping that the next post would be the much anticipated OES-OWSM Custom Assertion, but things have been very busy coming out of Open World. Oddly, I'm working with multiple customers that have been looking for a solution to the following use case:

WLS makes a Web-Services call using JAX-WS to Oracle Service Bus (OSB) passing the identity of the caller using SAML Sender Vouches (SV). OSB serves as an active-intermediary and process the SAML Assertion. OSB then goes and calls a Business Service propagating the user's identity, again using SAML SV.

What makes this use case a little tricky is that OSB at present does not understand WS-Policy 1.2 Assertions, and the JAX-WS stack on WLS does not understand the OSB proprietary assertions. This means that local policy needs to be applied 4 places

  • JAX-WS Client using WS-Policy 1.2
  • OSB Proxy Service using OSB Policy
  • OSB Business Service using OSB Policy
  • WLS Web Services service using WS-Policy 1.2


This post will cover the specific policies and how to apply them at each point.

JAX-WS Client using WS-Policy 1.2



You need to use a ClientPolicyFeature, and load the actual policy from an InputStream. In the example below, I'm running inside a web-application and packaged the policy.xml in the WEB-INF directory.


ClientPolicyFeature cpf =
new ClientPolicyFeature();



InputStreamPolicySource ps = new InputStreamPolicySource(this.getServletContext().getResourceAsStream("/WEB-INF/policy.xml"));

cpf.setEffectivePolicy(ps);


Dispatch dispatch = service.createDispatch(portName,
SOAPMessage.class, Service.Mode.MESSAGE, new WebServiceFeature[] {cpf});




The policy that I'm using is just the standardWssp1.2-2007-Saml1.1-SenderVouches-Wss1.0.xml.


<?xml version="1.0" encoding="windows-1252" ?>
<wsp:Policy wssutil:Id="Wssp1.2-2007-Saml1.1-SenderVouches-Wss1.0.xml" xmlns:wssutil="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<ns1:AsymmetricBinding xmlns:ns1="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<ns1:InitiatorToken>
<wsp:Policy>
<ns1:X509Token ns1:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<ns1:WssX509V3Token10 />
</wsp:Policy>
</ns1:X509Token>
</wsp:Policy>
</ns1:InitiatorToken>
<ns1:RecipientToken>
<wsp:Policy>
<ns1:X509Token ns1:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/Never">

<wsp:Policy>
<ns1:WssX509V3Token10 />
</wsp:Policy>
</ns1:X509Token>
</wsp:Policy>
</ns1:RecipientToken>
<ns1:AlgorithmSuite>
<wsp:Policy>
<ns1:Basic256 />
</wsp:Policy>
</ns1:AlgorithmSuite>
<ns1:Layout>
<wsp:Policy>
<ns1:Lax />
</wsp:Policy>
</ns1:Layout>
<ns1:IncludeTimestamp />

<ns1:ProtectTokens />
<ns1:OnlySignEntireHeadersAndBody />
</wsp:Policy>
</ns1:AsymmetricBinding>
<ns2:SignedSupportingTokens xmlns:ns2="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<ns2:SamlToken ns2:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<ns2:WssSamlV11Token10 />
</wsp:Policy>
</ns2:SamlToken>
</wsp:Policy>
</ns2:SignedSupportingTokens>
<ns3:Wss10 xmlns:ns3="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<ns3:MustSupportRefKeyIdentifier />
<ns3:MustSupportRefIssuerSerial />

</wsp:Policy>
</ns3:Wss10>
</wsp:Policy>

On the client, beside setting up the policy, you'll also need to configure a SAMLCredentialMapper and a PKICredentialMapper. The PKICredentialMapper needs to have access to a keystore that contains the Private Key used to sign the request.

OSB Proxy Service using OSB Policy


The OSB policy is really just the WLS 9.2 Web Services stack.. Basically, you need to create a WS-Policy and attach it to the request in the proxy service. Also, need to make sure to configure the proxy service to process the WS-Security header.




The actual policy is below.

<?xml version="1.0"?>

<wsp:Policy
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wssp="http://www.bea.com/wls90/security/policy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wls="http://www.bea.com/wls90/security/policy/wsee#part"
wsu:Id="saml-policy"
>

<wssp:Identity>
<wssp:SupportedTokens>
<wssp:SecurityToken TokenType="http://docs.oasis-open.org/wss/2004/01/oasis-2004-01-saml-token-profile-1.0#SAMLAssertionID">
<wssp:Claims>
<wssp:ConfirmationMethod>sender-vouches</wssp:ConfirmationMethod>
</wssp:Claims>
</wssp:SecurityToken>
</wssp:SupportedTokens>
</wssp:Identity>

<wssp:Integrity>

<wssp:SignatureAlgorithm URI="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<wssp:CanonicalizationAlgorithm
URI="http://www.w3.org/2001/10/xml-exc-c14n#"/>

<wssp:Target>
<wssp:DigestAlgorithm
URI="http://www.w3.org/2000/09/xmldsig#sha1" />
<wssp:MessageParts
Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">
wsp:Body()
</wssp:MessageParts>
</wssp:Target>

<wssp:Target>
<wssp:DigestAlgorithm URI="http://www.w3.org/2000/09/xmldsig#sha1" />
<wssp:MessageParts
Dialect="http://www.bea.com/wls90/security/policy/wsee#part">
wls:SecurityHeader(Assertion)
</wssp:MessageParts>
</wssp:Target>

</wssp:Integrity>


<wssp:MessageAge/>

</wsp:Policy>



Setting up OSB to consume the SAML Assertion and validate the signature requires the creation of a SAML Identity Asserter. NOTE: In the asserting party configuration, OSB uses a relative path Remember this if you run into trouble getting OSB to understand the assertion.

OSB Business Service using OSB Policy


This was really the only "tricky" part. I had to modify the saml-sv policy to sign the timestamp. The policy on the business service doesn't require it, but it does expect the Timestamp to have a wsu:Id, and making OSB sign it does exactly that. The set-up in OSB is the same as the proxy service, just configure the policy on the request.

The policy on the business service is as follows:


<?xml version="1.0"?>

<wsp:Policy
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wssp="http://www.bea.com/wls90/security/policy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wls="http://www.bea.com/wls90/security/policy/wsee#part"
wsu:Id="saml-policy-to-business-service"
>

<wssp:Identity>
<wssp:SupportedTokens>
<wssp:SecurityToken TokenType="http://docs.oasis-open.org/wss/2004/01/oasis-2004-01-saml-token-profile-1.0#SAMLAssertionID">
<wssp:Claims>
<wssp:ConfirmationMethod>sender-vouches</wssp:ConfirmationMethod>
</wssp:Claims>
</wssp:SecurityToken>
</wssp:SupportedTokens>
</wssp:Identity>

<wssp:Integrity>

<wssp:SignatureAlgorithm URI="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<wssp:CanonicalizationAlgorithm
URI="http://www.w3.org/2001/10/xml-exc-c14n#"/>

<wssp:Target>
<wssp:DigestAlgorithm
URI="http://www.w3.org/2000/09/xmldsig#sha1" />
<wssp:MessageParts
Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">
wsp:Body()
</wssp:MessageParts>
</wssp:Target>

<wssp:Target>
<wssp:DigestAlgorithm
URI="http://www.w3.org/2000/09/xmldsig#sha1" />
<wssp:MessageParts
Dialect="http://www.w3.org/TR/1999/REC-xpath-19991116">
wsp:GetHeader(./wsse:Security/wsu:Timestamp)
</wssp:MessageParts>
</wssp:Target>

<wssp:Target>
<wssp:DigestAlgorithm URI="http://www.w3.org/2000/09/xmldsig#sha1" />
<wssp:MessageParts
Dialect="http://www.bea.com/wls90/security/policy/wsee#part">
wls:SecurityHeader(Assertion)
</wssp:MessageParts>
</wssp:Target>

</wssp:Integrity>

<wssp:MessageAge/>

</wsp:Policy>



When adding a business service that requires signing, the proxy service has to have a Service Key Provider. This is really just a wrapper around the policies stored in the PKI Mapper. Basically, you select an alias to use to sign the message going to that business service.



Inside of the realm, in order to be able to configure a Service Key Provider, the PKI CredMapper needs to exist. In addition, the SAML Credential Mapper is required to generate the SAML Assertion.

WLS Web Services service using WS-Policy 1.2


This is pretty straight forward.



@WebService
@Policy(uri = "policy:Wssp1.2-2007-Saml1.1-SenderVouches-Wss1.0.xml")
public class Test {


public String hello(String in) {
System.out.println("=====>"+in);
return "Hello "+in;
}

}



Summary


In setting up a scenario as complicated as this there will undoubtedly be challenges. Use the debug settings inside of WLS, they are your friend. In my set-up I added the following JAVA_OPTIONS to my setDomainEnv.cmd


set JAVA_OPTIONS=%JAVA_OPTIONS% %JAVA_PROPERTIES% -Dwlw.iterativeDev=%iterativeDevFlag% -Dwlw.testConsole=%testConsoleFlag% -Dwlw.logErrorsToConsole=%logErrorsToConsoleFlag%
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.wsee.verbose=* -Dcom.sun.xml.ws.transport.http.HttpAdapter.dump=true -Dweblogic.xml.crypto.encrypt.verbose=true -Dweblogic.xml.crypto.dsig.debug=true-Dweblogic.xml.crypto.dsig.verbose=true -Dweblogic.wsee.security.debug=true -Dweblogic.wsee.security.verbose=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.xml.crypto.wss.debug=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.xml.crypto.wss.verbose=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.xml.crypto.keyinfo.debug=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.xml.crypto.keyinfo.verbose=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.xml.crypto.dsig.debug=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.xml.crypto.dsig.verbose=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.xml.crypto.encrypt.debug=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.xml.crypto.encrypt.verbose=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.servlet.DIEnabled=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.debug.DebugSecuritySAMLService=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.debug.DebugSecuritySAMLCredMap=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.debug.DebugSecuritySAMLAtn=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.debug.DebugSecuritySAMLLib=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.debug.DebugSecuritySAML2Service=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.debug.DebugSecuritySAML2CredMap=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.debug.DebugSecuritySAML2Atn=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.debug.DebugSecuritySAML2Lib=true
set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.debug.DebugSecurityCredMap=true


This gives you good visibility into where the issues are. Also can't hurt to have the weblogic.security.atn and weblogic.security.credmap debug categories on. When trying to figure out what is going on, more information is better. Be patient, this will spit out a lot of information, but look through it and you can normally get to the issue.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.