8 Replies Latest reply on Sep 17, 2012 12:42 PM by asoldano

    Hacking WS-Trust on JBoss AS 7 [was: Metro in JBoss 7 HowTo]

    okidoky

      ... or rather ... How do I make JBoss 7 use Sun Metro instead of CXF ?

       

      The only trace I found on the internet about this was this:

      https://community.jboss.org/thread/173486

       

      Which states this:

       

      --- START ---

      remove

       

      <module name="org.jboss.modules"/>

       

      declaration from both

       

      * modules/javax/xml/soap/api/main/module.xml

      * modules/javax/xml/ws/api/main/module.xml

       

      The reason is these API jars contain some classloading hacks that are trying to lookup JBossAS specific JAXWS & SAAJ impls.

      If you'll remove this org.jboss.modules dependency, the hack will become disabled.

       

      Next U'll need to extend

       

      * modules/sun/jdk/main/module.xml

       

      to include Sun RI JAXWS & SAAJ impl packages, plus define SAAJ Sun RI services & JAXWS Sun RI services in

       

      sun/jdk/main/service-loader-resources/META-INF/services

       

      folder.

       

      Finally U'll need to add

       

      <module name="sun.jdk"/>

       

      dependency to both

       

      * modules/javax/xml/soap/api/main/module.xml

      * modules/javax/xml/ws/api/main/module.xml

       

      This way Sun RI impl classes should be used from any deployment that is depending on these modules.

      ---END---

       

      Removing org.jboss.modules from the two xml files, and adding sun.jdk as a dependency is easy.

      Then the mystery part. Adding "something" to sun.jdk.

      I figure this: javax.xml.ws

      What else???

      I'm adding this to my war/WEB-INF/lib:

      webservices-api.jar

      webservices-extra-api.jar

      webservices-extra.jar

      webservices-rt.jar

      webservices-tools.jar

       

      In my web-service test method, I'm deliberately throwing an exception, to see if the stacktrace reveals that I came there through metro and not through cxf.

      This did not work, because even though I made the above change, cxf remained fully functional.

       

      It's been weeks now to get stuff working. Compiling CXF from doesn't work, JBoss 7.1.1 and 7.1.2 having too old CXFs, 7.2.0 nightly build has other changes and is a "nightly" and not "QA'ed".

      CXF 2.6.1 MEX not working.

      ps. I'm using 7.2.0.Final-SHAPSHOT from August 22.

       

      So. Does anyone know how I can make JBoss 7 use Metro instead of CXF for web-services?

      I'm literally at my wits' end with this whole web-services (need WS-Trust) thing. I can't / don't want to, use CXF, I need to / want to use Metro. Is this possible?

        • 1. Re: Metro in JBoss 7 HowTo
          ropalka

          It's been weeks now to get stuff working. Compiling CXF from doesn't work, JBoss 7.1.1 and 7.1.2 having too old CXFs, 7.2.0 nightly build has other changes and is a "nightly" and not "QA'ed".

          AS 7.2.0 is QA'ed on daily basis and all webservices tests are passing on top of it.

           

          CXF 2.6.1 MEX not working.

          ps. I'm using 7.2.0.Final-SHAPSHOT from August 22.

          What you mean with CXF 2.6.1 MEX not working. Are you seeing some bug?

           

          I'm literally at my wits' end with this whole web-services (need WS-Trust) thing. I can't / don't want to, use CXF, I need to / want to use Metro. Is this possible?

          CXF delivered with AS 7.2.0 provides WS-Trust support.

          What Metro does have and CXF doesn't WRT WS-Trust?

          • 2. Re: Metro in JBoss 7 HowTo
            asoldano

            Just FYI Mike, JBossWS 4.1.0.Beta2 has just been installed on AS 7 master, so the latest AS 7.2.0.Alpha1-SNAPSHOT should now include it as well as Apache CXF 2.6.2. You can use that for now. Hopefully by the end of September JBossWS 4.1.0.will be Final/GA and released in binary distribution, some new features / fixes are still to be worked before that.

             

            Speaking of Metro, it's most likely possible to have it running on AS 7 for basic SOAP functionalities by hacking the modules etc, but that's not an easy task if you don't have experience with jboss modular classloading (and possibly followed the AS-WS integration and design a bit in the past); besides that, it's not something we really support. Btw, I believe Apache CXF WS-Trust implementation is *at least* as good as the Metro one, to me even better.

             

            I've replied you at https://community.jboss.org/wiki/WS-TrustWithJBossWS-CXFOnJBossAS71#comment-10582 with some links on the documentation regarding building JBossWS-CXF.

            • 3. Re: Metro in JBoss 7 HowTo
              okidoky

              Hello Richard, The build and test cases are very impressive, and a nightly build might have to do. There is only so much that test cases will cover of course. To use it in a production environment might make people nervous though.

              It also built out of the box, without me having to tinker with pom.xmls and hunt and gather and guess for repositories to solve missing dependencies. I ran into that problem trying to build CXF and the wstrust sample.

               

              It's a long story. My goal is to provide WS-Trust security to a webservice. The webservice is going to transfer information between third parties across the internet (but just WLANs for now).

              I started off with PicketLink think that that would provide what I needed. I got the sample working, but the only thing I could get out of it is web-browser based SSO features. The contributed (Talend?) STS appears to work. What I need is a remote Java client making WS calls. For that it needs org.picketlink.trust packages, which apparently aren't implemented yet for JBoss 7. Plus it wasn't clear at all how to provide security without  blanketing the web-server with HTML redirects (to web-browser login page). So that was game over.

               

              I then tried to see if I could get this going with JBossWS-CXF. I couldn't immediately figure out from the documentation that one could choose from things like Axis2, CXF, or Metro. At first I though, yes, I have a choice, but then it became clear that JBoss is tightly integrated with CXF (only). Am I wrong?

               

              Proceeding with CXF, basic web-services worked very well. @WebService. deploy. wsconsume.sh. new Service(), etc. worked great.

              But then that WS-Trust can of worms again. Hand code WSDL, copy-pasting bits, trial and error, etc.

              What I did is I tried to make the wstrust demo work, as is. Problem with that was the maven build process that comes with it, didn't work because of repository errors. I tried to poke around with reposity and plugin reposity urls, googling around to see where around the net I could find a close match to what it wants. Often I can muddle my way around when I run into repository issues, but this time I got stuck at one point.

              I then tried to just try to make sense what that demo is made up off. Created a build process, made sure all the right stuff lands in the right places. This eventually deployed. The url for the app and the sts worked, and produced the wsdl it came with.

              Then the trouble started. At runtime, the Java client (standalone Java app, not from inside JBoss), error: "None of the policy alternatives could be satisfied.". I created a topic about this here: https://community.jboss.org/message/755232

              I couldn't for the longest time figure out what the heck this meant. "Alternatives"? What the heck is an "alternative". Can't it just do its thing and not look for "alternatives", and if it's not happy about a specific thing, just report what exactly it is that it is unhappy about? eg. "require token, but configuration not specifying the location of the sts where to get one" (just as an example). Very confusing.

              The way I gathered the jar files needed at runtime for the Java client, was to let it run into class-not-found exceptions, and then searching the jar files for that class. I have scripts for that that lets me home in on the missing jars very quickly.

              Error refused to go away. I then started to clue in that there are all these other cxf-rt-* jar files, offering various (optional) features that it would dynamically try to resolve at runtime. At the same time, someone asked me if cxf-rt-ws-security-2.6.1.jar is in the classpath. I tossed in all the jar files. Error stubbornly refused to go away. Trying to make sure that it's there at runtime, I do: Class.forName("org.apache.cxf.ws.security.policy.model.AsymmetricBinding");

              Class resolves, but error remains. I forgot to mention, I've made it log "ALL", which revealed that "AsymmetricBinding is not supported". Which is why I tried the above Class.forName thing.

              So I got stuck. No answers to be found anywhere. No related discussions with solutions anywhere.

               

              My previous project was on JBoss 4.something, and there I used Metro, and made web.xml tie in a url to a servlet that comes with Metro. But now we want to upgrade to JBoss 7, and I need those new WS-Security features (WS-Trust specifically). PicketLink didn't do, and got stuck with CXF.

               

              So then I tried to make a Metro based client, thinking that it ought to be able to deal with a web-service that's served up by CXF, because after all, we're dealing with "standards". Seems reasonable.

              But then Metro wasn't happy, because it wanted to access a URL with "/mex" tagged on to the end. What the heck is "mex"... Why? Can I tell it not to? Is there anything in the wsdl that makes it do that?

              Supposedly this metadata feature emerged some time in 2009. From what I gathered, CXF didn't get this until either earlier this year or end last year.

              JBoss 7.1.1 uses CXF 2.4.6, but mex wasn't supported until 2.5.something. JBoss 7.2.0 which is what I'm using now, has 2.6.2, which should have it.

              But CXF isn't making availale that "mex" url of the sts (wstrust sample). 404, error. Metro not happy. No way in Metro to tell it not to look for metadata. Metro assuming that even when wsdl doesn't specify it, that it's there and for it to go and get it. Error makes it cop out with an exception.

              So much for the "standards". Now Metro can't access "older" web-services?

              So either I find a workaround to make Metro not request mex, or convince CXF to make available mex. Can't find anything about this described in any document, or any online discussion someone else might have had about it.

               

              Ok, next. Use Metro on the server side. CXF appears pretty tightly integrated with JBoss. But JBoss uses a module class-loading / resolution process, which ought to make it possible to make a specific app opt for an alternative (be it Metro, or Axis2, whatever). Not seeing a module for it, or anything that hints its already there. Searching for related information, I found one single message: https://community.jboss.org/thread/173486

              Incomplete, left guessing, again. I tried to mock around with injecting some class-packages into sun.jdk module, but I could not make @WebService tie in to Metro. To test, what I did is made the method implementation throw an exception, which would reveal what called it. Either CXF was calling it, or nothing would work because I mocked with JBoss' configuration.

              Stuck, again.

               

              So:

              * PicketLink doesn't do remote Java client based incoming WS-Trust.

              * CXF doesn't pick up the security "features" "alternatives" (or whatever they're called) from the cfx-rt-*.jars even though they're available on the classpath.

              * Metro can't call CXF because CXF isn't making /mex urls available

              * Metro can't be installed on the server because JBoss is too cozy with CXF

               

              My appologies for being a little frustrated, but I'm normally a lot more productive after weeks of doing stuff...

               

              The current JBoss I'm using is the 7.2.0.Final-SHAPSHOT from Aug 22 which had a "stable" label on it, which I'm assuming, means, it passed all the unit tests. Very cool all those unit tests btw. I hope they're complete enough. (does it have any concurrent testing, simulating multiple incoming calls, kind of like a WS load test, stuff like that?)

               

              I'm assuming that the latest-latest nightly build has further upgrades, changes, bug fixes, that makes CXF work better and that it resolves the AsymmetricBinding at runtime this time... I'll let you know what happens.

              If it works, then I got finally past this problem, and the fun can begin, making an STS tie into user accounts at runtime (through those callbacks).

              • 4. Re: Metro in JBoss 7 HowTo
                okidoky

                Alessio,

                 

                downloading latest nightly now. jbossws-cxf build process failed, repo error. I've added a comment there.

                I'll let you know what if the latest 7.2.0 (that has the newer cxf beta2), ends up resolving AsymmetricBinding.

                • 5. Re: Metro in JBoss 7 HowTo
                  asoldano

                  I then tried to see if I could get this going with JBossWS-CXF. I couldn't immediately figure out from the documentation that one could choose from things like Axis2, CXF, or Metro. At first I though, yes, I have a choice, but then it became clear that JBoss is tightly integrated with CXF (only). Am I wrong?

                  We never integrated Axis2; we used to have Metro integration but that has been dropped few years ago. ATM, JBossWS is tighly integrated with Apache CXF.

                   

                   

                  Proceeding with CXF, basic web-services worked very well. @WebService. deploy. wsconsume.sh. new Service(), etc. worked great.

                  But then that WS-Trust can of worms again. Hand code WSDL, copy-pasting bits, trial and error, etc.

                  What I did is I tried to make the wstrust demo work, as is. Problem with that was the maven build process that comes with it, didn't work because of repository errors.

                  Have you tried the Apache CXF wstrust demo or JBossWS-CXF WSTrustTestCase from the jbossws-cxf 4.1.0.Beta2 or trunk testsuite? Again, the latter is tested every day here and should be working.

                  Keep in mind that unfortunately if you mix artifacts you get from different maven repositories that are not what you're supposed to use (see my previous message on how to configure maven), you might even end up in having an inconsistent local maven repository. So also consider moving away your current repo and trying with a fresh / empty one after having properly configured Maven.

                   

                  I then tried to just try to make sense what that demo is made up off. Created a build process, made sure all the right stuff lands in the right places. This eventually deployed. The url for the app and the sts worked, and produced the wsdl it came with.

                  Then the trouble started. At runtime, the Java client (standalone Java app, not from inside JBoss), error: "None of the policy alternatives could be satisfied.". I created a topic about this here: https://community.jboss.org/message/755232

                  I couldn't for the longest time figure out what the heck this meant. "Alternatives"? What the heck is an "alternative". Can't it just do its thing and not look for "alternatives", and if it's not happy about a specific thing, just report what exactly it is that it is unhappy about? eg. "require token, but configuration not specifying the location of the sts where to get one" (just as an example). Very confusing.

                  No offense meant, but "policy alternative" has a very specific meaning from the WS-Policy specification. Basically, a policy can be composed of alternatives which are a group of policy assertions. When verifying if a policy is met, each alternative is verified. If none of them is satisfied, the policy is not met. Now, the message here come from the Apache CXF policy engine and basically tells you that the message your client created is not satifying one of the policies in the endpoint (or sts, depending on which call is being executed) wsdl contract. There could be multiple reasons for that, either some cxf components are missing in the classpath, or the policy you added into the wsdl is actually not supported by cxf, or ... ?

                   

                  The way I gathered the jar files needed at runtime for the Java client, was to let it run into class-not-found exceptions, and then searching the jar files for that class. I have scripts for that that lets me home in on the missing jars very quickly.

                  Error refused to go away. I then started to clue in that there are all these other cxf-rt-* jar files, offering various (optional) features that it would dynamically try to resolve at runtime. At the same time, someone asked me if cxf-rt-ws-security-2.6.1.jar is in the classpath. I tossed in all the jar files. Error stubbornly refused to go away. Trying to make sure that it's there at runtime, I do: Class.forName("org.apache.cxf.ws.security.policy.model.AsymmetricBinding");

                  Class resolves, but error remains. I forgot to mention, I've made it log "ALL", which revealed that "AsymmetricBinding is not supported". Which is why I tried the above Class.forName thing.

                  So I got stuck. No answers to be found anywhere. No related discussions with solutions anywhere.

                  You might probably use a different approach here. Consider having a look at the jbossws-cxf testsuite; you can look at the maven dependency:tree for the testsuite and figure out the required dependencies. All the cxf jars that are installed in JBoss AS are definitely needed anyway.

                   

                  So then I tried to make a Metro based client, thinking that it ought to be able to deal with a web-service that's served up by CXF, because after all, we're dealing with "standards". Seems reasonable.

                  But then Metro wasn't happy, because it wanted to access a URL with "/mex" tagged on to the end. What the heck is "mex"... Why? Can I tell it not to? Is there anything in the wsdl that makes it do that?

                  Supposedly this metadata feature emerged some time in 2009. From what I gathered, CXF didn't get this until either earlier this year or end last year.

                  JBoss 7.1.1 uses CXF 2.4.6, but mex wasn't supported until 2.5.something. JBoss 7.2.0 which is what I'm using now, has 2.6.2, which should have it.

                  But CXF isn't making availale that "mex" url of the sts (wstrust sample). 404, error. Metro not happy. No way in Metro to tell it not to look for metadata. Metro assuming that even when wsdl doesn't specify it, that it's there and for it to go and get it. Error makes it cop out with an exception.

                  So much for the "standards". Now Metro can't access "older" web-services?

                  So either I find a workaround to make Metro not request mex, or convince CXF to make available mex. Can't find anything about this described in any document, or any online discussion someone else might have had about it.

                   

                  Metro definititely has an aggressive approach here. I believe some work has been done on Apache CXF side to support WS-MetadataExchange ("mex") though. I'll check everything is actually in place from this point of view on next week, this is indeed an interesting feedback. And of course, yeah, we're dealing with standards, so you should really be able to use a standalone Metro client to invoke the endpoint running on JBoss AS w/ CXF.

                   

                   

                  Ok, next. Use Metro on the server side.

                   

                  Frankly, to me this is the least viable approach.

                   

                  I see you replied to other posts while I was writing here, will check and reply again.

                  • 6. Re: Metro in JBoss 7 HowTo
                    okidoky

                    Alessio, my appologies for all the ruckus. I just found the problem, but not the solution. My client was a standalone Java app that I threw a bunch of jar files at, which includes all the ones starting with cxf-rt, plus a bunch of other ones.

                    The mystery "AsymmetricBinding is not supported" error (only revealed after changing Logger to log "ALL") just wouldn't go away, hence all the desperate attempts to somehow provide WS-Trust in any shape or form, didn't care how.

                     

                    I then discovered the org.jboss.ws.cxf.jbossws-cxf-client module, thinking, hey! a collection of stuff that would equip an app with what's needed to make CXF calls. I looked at the jar files it listed, and threw those at my standalone Java app.

                    Still, the error persisted.

                    I then decided to see what would happen if I, instead of making the call from the standalone Java app, to make the call from inside JBoss. I told the war app to add org.jboss.ws.cxf.jbossws-cxf-client to the Dependecies listed in war/META-INF/MANIFEST.MF.

                    I added an unsecure little door-knocker class with a knock method.

                    I added a test class in my standalone Java app, that would knock the (unsecure) door. So a quick and easy way to make the user (me) trigger a test. I could have had a webpage with a button on it as well.

                    The knock method tries to do the same thing as the initial test does, which is to make that secure call.

                    And what do you know. It *actually* went to try to fetch a token from the sts. Things were misconfigured and there were other errors, but at least there is evidence of it using AsymmetricBinding, and it trying to contact the STS.

                    So now I can proceed.

                     

                    But the question remains - which other jar files are needed for a standalone Java application to be able to make remove CXF based web service calls? What the org.apache.cxf and the org.jboss.ws.cxf.jbossws-cxf-client modules lists wasn't enough. It's possible that I missed one, but from the looks of it, it needs something else.

                    That security rt cxf jar was there - Class.forName on that AsymmetricBinding class succeeded. But just that class existing wasn't enough. Some other class, engine, is needed that makes it go look and tie in those features at runtime.

                    Thing is, there isn't anything in the log file (client side) that provides any hint as to what parts it would have like to have seen.

                    It would be nice if it was a little more verbose, and make the prediction that it "normally" ought to have found jar such and such (or class such and such), and that as a result of it not being found, that certain features will not be available.

                    That alone would have saved me almost 3 weeks of horsing around.

                     

                    Second, the solution to this, possibly just a list of jar files (or a script that shows which jar files are needed - which dissects the needed jar list from a given JBoss version - so that when things change, you don't end up with an outdated document) ought to be documented somewhere. Surely, someone else is going to try to make a standalone Java program, or make calls from another app that is not a JBoss server.

                     

                    Lastly, it's interesting that, possibly, as is, right now, Metro can not do WS-Trust with a CXF server. Unless that tagged on /mex url becomes automagically available.

                    My thinking on that one, is that *if* the wsdl advertises the (extra?) metadata, that CXF then goes ahead and makes avaibable this mystery /mex service (that apparently does GETs and POSTs and whatnots), and that Metro "ought to" not make assumptions about mex being available when the wsdl doesn't list it (which might be considered a bug in Metro - which should be reported - or at least feedback ought to be requested on this issue - I can post a report about my findings, since I've already spend time banging my head into this...).

                    *Maybe* there could a flag somewhere that makes CXF make available mex even though wsdl doesn't advertise it - just so that clients like Metro that require this (wrongfully), don't end up failing.

                    *Or*, have CXF add mex always. I don't know when mex should be added - perhaps only  with this WS-Trust stuff? Or perhaps for other ws security features. Not needed for simple unsecure ws calls I would think (will have to verify that).

                     

                    Anyway, this whole thing costed a lot of time, but hopefully some good will come from this...

                    • 7. Re: Metro in JBoss 7 HowTo
                      asoldano

                      Hi Mike,

                      I'll comment later on the classpath / client topic.

                      Mike P wrote:

                       

                      Lastly, it's interesting that, possibly, as is, right now, Metro can not do WS-Trust with a CXF server. Unless that tagged on /mex url becomes automagically available.

                      My thinking on that one, is that *if* the wsdl advertises the (extra?) metadata, that CXF then goes ahead and makes avaibable this mystery /mex service (that apparently does GETs and POSTs and whatnots), and that Metro "ought to" not make assumptions about mex being available when the wsdl doesn't list it (which might be considered a bug in Metro - which should be reported - or at least feedback ought to be requested on this issue - I can post a report about my findings, since I've already spend time banging my head into this...).

                      *Maybe* there could a flag somewhere that makes CXF make available mex even though wsdl doesn't advertise it - just so that clients like Metro that require this (wrongfully), don't end up failing.

                      *Or*, have CXF add mex always. I don't know when mex should be added - perhaps only  with this WS-Trust stuff? Or perhaps for other ws security features. Not needed for simple unsecure ws calls I would think (will have to verify that).

                      I did a bit of additional investigation on this topic today. Basically, Apache CXF is able to reply to WS-MEX requests sent to "/mex". The problem is with properly configuring the STS endpoint on JBoss AS.

                      You need to have the JBoss Web layer deal with HTTP messages to the /mex subpath, for instance by having a web.xml descriptor as follows (please note the wildcard in the url pattern):

                       

                      <web-app ...>

                         <servlet>

                            <servlet-name>TestSecurityTokenService</servlet-name>

                            <servlet-class>org.jboss.test.ws.jaxws.samples.wsse.policy.trust.SampleSTS</servlet-class>

                         </servlet>

                         <servlet-mapping>

                            <servlet-name>TestSecurityTokenService</servlet-name>

                            <url-pattern>/SecurityTokenService/*</url-pattern>

                         </servlet-mapping>

                      </web-app>

                       

                      Besides that, I unfortunately found a bug in the jbossws-cxf SubjectCreatingInterceptor which basically block any WS-MEX call, see https://issues.jboss.org/browse/JBWS-3543 . It's fixed on jbossws-cxf trunk and will be in next release. I'm updating the doc at https://docs.jboss.org/author/display/JBWS/WS-Trust+and+STS#WS-TrustandSTS-ApacheCXFSTS soon.

                       

                      This said, there're many complaints on the net regarding Metro default behaviour wrt WS-MetadataExchange and STS endpoints; btw Glen Mazza also created a WSIT / Metro improvement ticket at http://java.net/jira/browse/WSIT-1586 long time ago (for a better configurability of Metro), but that's not been worked yet.

                      • 8. Re: Metro in JBoss 7 HowTo
                        asoldano

                        Alessio Soldano wrote:

                         

                        Hi Mike,

                        I'll comment later on the classpath / client topic.

                         

                        I've added some doc in the quick start: https://docs.jboss.org/author/display/JBWS/Quick+Start#QuickStart-Resolvingdependenciesandrunningtheclient

                        Hope this helps.