[Apiman-dev] Apiman - WS Security policy
Benjamin Kastelic
kastelic.benjamin at gmail.com
Tue Mar 29 13:42:28 EDT 2016
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 at 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 at 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 at redhat.com
> >>> <mailto:eric.wittmann at 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 at redhat.com
> >>>> <mailto:eric.wittmann at redhat.com>
> >>>> <mailto:eric.wittmann at 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 at redhat.com
> >>>> <mailto:eric.wittmann at redhat.com><mailto:eric.wittmann at redhat.com>
> >>>> <mailto:eric.wittmann at redhat.com
> >>>> <mailto:eric.wittmann at 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 at redhat.com
> >>>> <mailto:eric.wittmann at redhat.com><mailto:eric.wittmann at redhat.com>
> >>>> <mailto:eric.wittmann at redhat.com
> >>>> <mailto:eric.wittmann at redhat.com>>
> >>>> <mailto:eric.wittmann at redhat.com
> >>>> <mailto:eric.wittmann at 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 at lists.jboss.org <mailto:Apiman-dev at lists.jboss.org>
> >>>> <mailto:Apiman-dev at lists.jboss.org>
> >>>> <mailto:Apiman-dev at lists.jboss.org
> >>>> <mailto:Apiman-dev at lists.jboss.org>>
> >>>> https://lists.jboss.org/mailman/listinfo/apiman-dev
> >>>>
> >>>>
> >>>>
> >>>>
> >>>>
> >>>> --
> >>>> Lp, Benjamin
> >>
>
>
--
Lp, Benjamin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/apiman-dev/attachments/20160329/665e221c/attachment-0001.html
More information about the Apiman-dev
mailing list