Thanks, I will definitely keep tabs on your progress :)

2016-03-30 16:02 GMT+02:00 Eric Wittmann <eric.wittmann@redhat.com>:
Note, here are a couple of JIRA issues created for these features in case you're interested in tracking our progress on them:

https://issues.jboss.org/browse/APIMAN-1072
https://issues.jboss.org/browse/APIMAN-1077

-Eric

On 3/30/2016 4:26 AM, Benjamin Kastelic wrote:
Just one more thing ...
If a SOAP API is published on Apiman and you request the WSDL by using
the gateway endpoint URL, you get the original WSDL - address is
pointing to the real endpoint URL and not the gateway endpoint URL.
I have solved this temporarily by adding URL rewrite policies to all
SOAP APIs, which replace the real endpoint URL with the gateway endpoint
URL.
I guess it would be best if this policy was handled by the gateway
internally so that you wouldn't have to worry by adding a correct policy
to the API configuration.

2016-03-29 20:29 GMT+02:00 Benjamin Kastelic
<kastelic.benjamin@gmail.com <mailto:kastelic.benjamin@gmail.com>>:

    OK, now I understand what you meant.
    I believe this would be a reasonable solution :)

    2016-03-29 20:18 GMT+02:00 Eric Wittmann <eric.wittmann@redhat.com
    <mailto:eric.wittmann@redhat.com>>:

        My plan was unclear!  Let's go with another example:

        Step 1 - the Gateway receives the following HTTP request:

        ----
        POST /apiman-gateway/MyOrg/soap-api/2.7 HTTP/1.1
        Host: www.example.org <http://www.example.org>

        Content-Type: application/soap+xml; charset=utf-8
        X-API-Key: API-KEY-FOR-ACTIVE-CLIENT
        SOAPAction: ExampleAction

        <?xml version="1.0"?>
        <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
           <soap:Header>
             <ns1:Header1 xmlns:ns1="uri:ns1">foo</ns1:Header1>
             <ns2:Header2 xmlns:ns2="uri:ns2">bar</ns2:Header2>
           </soap:Header>
           <soap:Body>
             <m:GetStockPrice xmlns:m="http://www.example.org/stock/RHT">
               <m:StockName>Red Hat</m:StockName>
             </m:GetStockPrice>
           </soap:Body>
        </soap:Envelope>
        ----

        We'll parse the first part of the envelope so that we can read
        the headers and make them available to any policies.  After
        that's done, we'll invoke the policy chain as per normal.
        However, because it's a SOAP api, there will exist a
        SOAPRequestInfo object in the policy context.  So policies can
        read and/or modify the soap information.  This class might look
        something like this:

        public class SOAPRequestInfo {
             private String action;
             private String encoding;
             private Map<QName, SOAPHeader> headers;
        }

        This allows interested policies (like your ws-security) policy
        to have easy access to all the soap related stuff.  It also
        allows you to alter these things.  Including
        adding/removing/modifying the SOAP headers.

        So let's assume that we have a policy which *adds* a SOAP header
        (ns3:AddedHeader) and another policy which *removes* one
        (ns2:Header2).  The policy code might look like this:

        SOAPRequestInfo soapInfo = context.getAttribute(
                 Constants.SOAP_INFO, (SOAPRequestInfo) null);
        soapInfo.getHeaders().remove(new QName("uri:ns2", "Header2"));
        soapInfo.getHeaders().put(
             new QName("uri:ns3", "AddedHeader"),
             createSoapHeader()
        );


        In that case, this is the HTTP request that will be sent/proxied
        to the back-end API:

        ----
        POST / HTTP/1.1
        Host: www.example.org <http://www.example.org>
        Content-Type: application/soap+xml; charset=utf-8
        SOAPAction: ExampleAction

        <?xml version="1.0"?>
        <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
           <soap:Header>
             <ns1:Header1 xmlns:ns1="uri:ns1">foo</ns1:Header1>
             <ns3:AddedHeader xmlns:ns3="uri:ns3">bar</ns3:AddedHeader>
           </soap:Header>
           <soap:Body>
             <m:GetStockPrice xmlns:m="http://www.example.org/stock/RHT">
               <m:StockName>Red Hat</m:StockName>
             </m:GetStockPrice>
           </soap:Body>
        </soap:Envelope>
        ----

        Sound reasonable?

        -Eric


        On 3/29/2016 1:42 PM, Benjamin Kastelic wrote:

            If I understand you correctly Eric, only the soap:Body part
            will be
            forwarded to the registered API?
            What if the API still needs to receive the soap:Header part?

            2016-03-29 15:34 GMT+02:00 Keith Babo <kbabo@redhat.com
            <mailto:kbabo@redhat.com>
            <mailto:kbabo@redhat.com <mailto:kbabo@redhat.com>>>:

                 Sounds cool to me.  Header policy will need to be QName and
                 DOM-aware, so that namespace-qualified headers can be
            added and
                 appropriate namespace definitions can be added to the
            DOM if
                 required.  Of course you already know all this, but
            pointing it out
                 makes me feel useful.

                  > On Mar 29, 2016, at 8:38 AM, Eric Wittmann
                 <eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
            <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>> wrote:
                  >
                  > That's an interesting idea.  It'd be harder to
            inject the headers
                 into the request than it is to inject HTTP request headers,
                 obviously.  But not impossible.  We'd need to be aware
            of the change
                 to any Content-Length that may be set.
                  >
                  > This makes the implementation slightly more
            complicated, because
                 I think the HTTP connector will need to be made smarter
            (it will
                 need to send the <soap:Envelope> and <soap:Header>
            sections first,
                 then just stream the remaining request body as-is.
                  >
                  > So perhaps what we have is this:
                  >
                  > 1.  <?xml version="1.0"?>
                  > 2.  <soap:Envelope
                 xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
                  > 3.    <soap:Header>
                  > 4.      <ns1:Foo actor="..."
            xmlns:ns1="uri:ns1">BAR</ns1:Foo>
                  > 5.    </soap:Header>
                  > 6.    <soap:Body>
                  > 7.      <m:GetStockPrice
                 xmlns:m="http://www.example.org/stock/Surya">
                  > 8.        <m:StockName>IBM</m:StockName>
                  > 9.      </m:GetStockPrice>
                  > 10.   </soap:Body>
                  > 11. </soap:Envelope>
                  >
                  > Lines 1-5 will be read and consumed by apiman
            *before* any
                 policies are executed.  We'll actually keep reading
            until we find
                 <soap:Body> in the request body.  We'll throw out
            everything before
                 line #6 from our in-memory buffer, resulting in a
            buffer with just
                 line #6 (and any extra bytes after that based on our
            I/O chunk size).
                  >
                  > The policies will be executed, which may result in
            soap headers
                 being added, modified, or removed.  If all policies
            pass, then we
                 proxy the request to the back-end.  Normally the HTTP
            connection
                 would simply send all bytes from the HTTP request
            as-is.  Instead,
                 we'll need to *generate* new content for lines 1-5,
            with the newly
                 modified soap headers.  Once the generated content is
            sent, then we
                 send the contents of the in-memory buffer (which
            contains line #6+
                 any additional bytes).  After that, we proxy the
            remaining bytes
                 from the HTTP request as-is.
                  >
                  > This may be starting to take shape.  :)
                  >
                  > Additional thoughts?
                  >
                  > -Eric
                  >
                  > PS:  @Keith - we'll likely have a separate Policy for
                 manipulating SOAP headers, rather than re-use the
            existing HTTP
                 headers policy.
                  >
                  > On 3/29/2016 8:13 AM, Keith Babo wrote:
                  >> Sounds like a reasonable first step to me.  Just to
            make life
                 slightly
                  >> more complicated, will the headers policy be
            updated to allow
                 add/remove
                  >> of SOAP:Headers? :-)
                  >>
                  >> ~ keith
                  >>
                  >>> On Mar 29, 2016, at 7:52 AM, Eric Wittmann
                 <eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
            <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>
                  >>> <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>>> wrote:
                  >>>
                  >>> OK so here's what I propose (feedback welcome):
                  >>>
                  >>> *If* an API's 'type' is set to SOAP, then we will
            *always* look
                 for a
                  >>> soap envelope in the body.  If no body is found or
            no soap
                 envelope is
                  >>> found in the body, then a standard apiman error
            will be thrown.
                  >>>
                  >>> If an envelope *is* found, then we will read the
            body of the HTTP
                  >>> request until we find "<soap:Body>".  We'll
            extract the
                 <soap:Header>
                  >>> and parse its children.  While parsing, we'll
            obviously keep
                 the data
                  >>> we read in a memory buffer.  Once parsing is done,
            we'll
                 include the
                  >>> soap headers, soap action, and the global encoding
            type in some
                 sort
                  >>> of soapinfo object and include that in the policy
            context.
                  >>>
                  >>> Finally, after all that is done, we'll process the
            request as
                 normal,
                  >>> executing the policy chain, then processing the
            request body,
                 etc. The
                  >>> entire request payload will still be processed
            (remember that
                 we saved
                  >>> the bytes we read in a memory buffer).
                  >>>
                  >>> So from the perspective of a policy, everything
            will look identical
                  >>> except that a SOAPInfo object will be available in
            the policy
                 context.
                  >>>
                  >>> Thoughts?
                  >>>
                  >>> -Eric
                  >>>
                  >>> On 3/28/2016 1:48 PM, Benjamin Kastelic wrote:
                  >>>> Yup, I agree. That would probably be best, since
            several
                 validators
                  >>>> (wss4j for example) require DOM Elements
                 (javax.xml.soap.SOAPHeader) to
                  >>>> function.
                  >>>>
                  >>>> Best regards,
                  >>>> Benjamin
                  >>>>
                  >>>> 2016-03-28 19:14 GMT+02:00 Eric Wittmann
                 <eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
            <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>
                  >>>> <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>>
                  >>>> <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>>>:
                  >>>>
                  >>>>   Thanks!  In that case, making the headers
            available as DOM
                 Element
                  >>>>   objects (perhaps with a simple QName based
            lookup) would be
                 best.
                  >>>>
                  >>>>   -Eric
                  >>>>
                  >>>>   On 3/28/2016 12:39 PM, Keith Babo wrote:
                  >>>>
                  >>>>       SOAP:Headers can be complex types.
            WS-Security is a good
                  >>>> example of
                  >>>>       this in practice.
                  >>>>
                  >>>>       ~ keith
                  >>>>
                  >>>>           On Mar 28, 2016, at 11:37 AM, Eric Wittmann
                  >>>>           <eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>
                  >>>> <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>><mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>>
                  >>>>           <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>
                  >>>>           <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>>>> wrote:
                  >>>>
                  >>>>           That's a bit hacky, but also sort of a
            genius
                 approach as
                  >>>>           well.  I'm
                  >>>>           actually a little bummed I didn't think
            of it.  :)
                  >>>>
                  >>>>           As for extending SOAP support - I was
            thinking that
                 I could
                  >>>>           make the
                  >>>>           relevant changes to apiman if you would
            be willing
                 to provide
                  >>>>           feedback/guidance/testing.  My SOAP
            expertise is
                 quite stale
                  >>>>           at this
                  >>>>           point, so having some eyeballs on these
            changes would be
                  >>>>           very useful.
                  >>>>
                  >>>>           To start off with, what pieces of the
            SOAP envelope
                 should
                  >>>>           be extracted
                  >>>>           prior to calling the policy chain?
            Some candidates are:
                  >>>>
                  >>>>           * The encoding style
                  >>>>           * All SOAP headers
                  >>>>           * SOAPAction (already available as an
            HTTP header)
                  >>>>           * ???
                  >>>>
                  >>>>           For the soap headers, all of the
            examples I've seen
                 take the
                  >>>>           following
                  >>>>           form:
                  >>>>
                  >>>>           <HeaderName
            xmlns="elementNS">Header-Value</HeaderName>
                  >>>>
                  >>>>           It can also have the optional "actor" or
                 "mustUnderstand"
                  >>>>           attributes.
                  >>>>           The SOAP envelope schema is pretty lax
            though, so
                 I'm not
                  >>>>           sure if the
                  >>>>           above is a convention or a rule.  Can
            headers be more
                  >>>>           complex than the
                  >>>>           above?
                  >>>>
                  >>>>           -Eric
                  >>>>
                  >>>>           On 3/26/2016 7:06 AM, Benjamin Kastelic
            wrote:
                  >>>>
                  >>>>               Hi,
                  >>>>
                  >>>>               I temporarily solved the problem by
            storing the
                 request
                  >>>>               body, which is
                  >>>>               contained in ApiRequest.rawRequest
            object, in a
                  >>>>               temporary buffer. I then
                  >>>>               process the data (authentication)
            and based on the
                  >>>>               results proceed with
                  >>>>               the policy chain or report a
            failure. Then in
                 the end()
                  >>>>               method of the
                  >>>>               requestDataHandler method I write
            the contents of my
                  >>>>               temporary buffer
                  >>>>               using super.write(IApimanBuffer).
            That way I can
                 forward
                  >>>>               the request to
                  >>>>               then ext policy in the chain. But
            this is still
                 a hacky
                  >>>>               way of doing
                  >>>>               this.
                  >>>>
                  >>>>               I would be glad to help with
            extending SOAP
                 support. But
                  >>>>               I would need a
                  >>>>               few pointers where to start. The
            way of storing SOAP
                  >>>>               headers in the
                  >>>>               ApiRequest object seems like a good
            idea.
                  >>>>
                  >>>>               2016-03-24 18:40 GMT+01:00 Eric
            Wittmann
                  >>>>               <eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>
                  >>>> <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>><mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>>
                  >>>>               <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>
                  >>>>               <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>>>
                  >>>>               <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>
                  >>>>               <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>
                 <mailto:eric.wittmann@redhat.com
            <mailto:eric.wittmann@redhat.com>>>>>:
                  >>>>
                  >>>>                   Hi Benjamin - thanks for the
            excellent
                 question.  I
                  >>>>               will do my best
                  >>>>                   to answer and note that I am
            CC'ing the
                 apiman-dev
                  >>>>               mailing list so
                  >>>>                   others can chime in.
                  >>>>
                  >>>>                   First let me say that a
            WS-Security policy
                 sounds
                  >>>>               great - we haven't
                  >>>>                   focused much on the WS-*
            protocols because
                 we get
                  >>>>               much more demand
                  >>>>                   for managing REST APIs than
            SOAP APIs.  That
                 said,
                  >>>>               better SOAP
                  >>>>                   support is certainly on the
            radar.  When that
                  >>>>               happens, my hope is
                  >>>>                   that processing the envelope
            might be a core
                 part of
                  >>>>               the gateway and
                  >>>>                   so implementing policies that
            use information in
                  >>>>               there will be
                  >>>>                   easier.  Perhaps your
            implementation can be the
                  >>>>               genesis of some of
                  >>>>                   that work!
                  >>>>
                  >>>>                   To your question - without core
            changes to
                 apiman,
                  >>>>               the approach you
                  >>>>                   *need* to take is to have your
            policy implement
                  >>>>               IDataPolicy.  I
                  >>>>                   believe you may have already
            tried that, and
                  >>>>               observed that you
                  >>>>                   cannot send proper policy
            failures from that
                  >>>>               method.  You are right
                  >>>>                   - that's something we will need
            to fix!  I
                 think you
                  >>>>               should be able
                  >>>>                   to throw a runtime exception
            from the
                  >>>>               write(IApimanBuffer chunk)
                  >>>>                   method if you detect an error.
            However,
                 this is a
                  >>>>               little bit hacky!
                  >>>>
                  >>>>                   Instead, I suggest (if you're
            up for it) that we
                  >>>>               perhaps work
                  >>>>                   together to bake SOAP support
            directly into
                 the core
                  >>>>               of apiman, such
                  >>>>                   that the SOAP envelope is
            read/parsed
                 *before* the
                  >>>>               policy chain is
                  >>>>                   executed.  We could expose, for
            example, the
                 SOAP
                  >>>>               headers as a
                  >>>>                   proper Map<> stored either in
            the context or
                 on the
                  >>>>               ApiRequest.
                  >>>>                   This would allow you to
            properly implement most
                  >>>>               (all?) WS-*
                  >>>>                   protocols as proper apiman
            policies in the
                  >>>>               apply(ApiRequest request)
                  >>>>                   method.
                  >>>>
                  >>>>                   Thoughts?
                  >>>>
                  >>>>                   -Eric
                  >>>>
                  >>>>
                  >>>>                   On 3/24/2016 7:58 AM, Benjamin
            Kastelic wrote:
                  >>>>
                  >>>>                       Greetings,
                  >>>>
                  >>>>                       I first thought to write
            this question as an
                  >>>>               issue on Github,
                  >>>>               but it
                  >>>>                       seemed better to write you
            a direct email.
                  >>>>
                  >>>>                       I am making a custom WS
            Security policy,
                 that
                  >>>>               reads the body and
                  >>>>                       check
                  >>>>                       the UsernameToken security
            header. This
                 works
                  >>>>               OK, but now I've
                  >>>>                       hit a wall.
                  >>>>
                  >>>>                       In the doApply method I get
            the rawRequest
                  >>>>               object and read the
                  >>>>                       body from
                  >>>>                       the ServletInputStream of
            the request. The
                  >>>>               problem I'm facing
                  >>>>               now is
                  >>>>                       that the input stream was
            read and it
                 can't be
                  >>>>               reset back to it's
                  >>>>                       initial state.
                  >>>>
                  >>>>                       I was also trying to
            implement the same
                 logic
                  >>>> in the
                  >>>>                       requestDataHandler
                  >>>>                       method, but I don't know if
            it is even
                 possible
                  >>>>               to send a failure
                  >>>>                       message to the request
            chain from there.
                  >>>>
                  >>>>                       Any suggesstions ?
                  >>>>
                  >>>>                       Best regards,
                  >>>>                       Benjamin
                  >>>>
                  >>>>
                  >>>>
                  >>>>
                  >>>>               --
                  >>>>               Lp, Benjamin
                  >>>>
                  >>>>
              _______________________________________________
                  >>>>           Apiman-dev mailing list
                  >>>> Apiman-dev@lists.jboss.org
            <mailto:Apiman-dev@lists.jboss.org>
            <mailto:Apiman-dev@lists.jboss.org
            <mailto:Apiman-dev@lists.jboss.org>>
                 <mailto:Apiman-dev@lists.jboss.org
            <mailto:Apiman-dev@lists.jboss.org>
            <mailto:Apiman-dev@lists.jboss.org
            <mailto:Apiman-dev@lists.jboss.org>>>
                  >>>>           <mailto:Apiman-dev@lists.jboss.org
            <mailto:Apiman-dev@lists.jboss.org>
                 <mailto:Apiman-dev@lists.jboss.org
            <mailto:Apiman-dev@lists.jboss.org>>>
                  >>>>           <mailto:Apiman-dev@lists.jboss.org
            <mailto:Apiman-dev@lists.jboss.org>
                 <mailto:Apiman-dev@lists.jboss.org
            <mailto:Apiman-dev@lists.jboss.org>>
                  >>>>           <mailto:Apiman-dev@lists.jboss.org
            <mailto:Apiman-dev@lists.jboss.org>
                 <mailto:Apiman-dev@lists.jboss.org
            <mailto:Apiman-dev@lists.jboss.org>>>>
                  >>>> https://lists.jboss.org/mailman/listinfo/apiman-dev
                  >>>>
                  >>>>
                  >>>>
                  >>>>
                  >>>>
                  >>>> --
                  >>>> Lp, Benjamin
                  >>




            --
            Lp, Benjamin




    --
    Lp, Benjamin




--
Lp, Benjamin



--
Lp, Benjamin