tomasguisasola / luasoap

LuaSOAP provides a very simple API that convert Lua tables to and from XML documents
57 stars 18 forks source link

[Question] Example for my use case? #14

Open jeremyjpj0916 opened 6 years ago

jeremyjpj0916 commented 6 years ago

Hello!

This library I believe should be able to meet a goal of mine. I would like to use OpenResty paired with this lib to do a few things:

Take an incoming SOAP payload and:

  1. Parse a SOAP Header element and get its value for processing AND remove that Header element from the SOAP payload.

  2. Append a few extra SOAP Header elements on the existing body before proxying off the payload to another service.

Can this library do this? Any chance you could give me a snippit after I luarocks install of what the above would look like? I imagine it is probably only 5-10 lines of code using your library?

Thanks, Jeremy

tomasguisasola commented 6 years ago

Hi Jeremy

This library I believe should be able to meet a goal of mine I think. I

would like to use OpenResty paired with this lib to do a few things:

Take an incoming SOAP payload and:

1.

Parse a SOAP Header element and get its value for processing AND remove that Header element from the SOAP payload. 2.

Append a few extra SOAP Header elements on the existing body before proxying off the payload to another service.

Can this library do this? Any chance you could give me a snippit after I luarocks install of what the above would look like? I imagine it is probably only 5-10 lines of code using your library?

As I understand you mean to create a kind of protocol filter. Well, I am not sure LuaSOAP will offer everything you need, but I am pretty sure it will help you understand how the protocol is managed and build your own solution. Take a look at the code! And let me show if there is something we could improve in the library.

Regards, Tomás

jeremyjpj0916 commented 6 years ago

@tomasguisasola Glad to see you are still active here on the repo 👍 ,

I think this lib will not work based on my other readings because you ignore SOAP:Header ? And the header is where all sorts of values tied to authn/authz happens in SOAP transactions which is what I need access to.

Essentially in sudo code this is what I want to be able to do:

<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope/"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<soap:Header>
  <wsse:Security>
 <wsse:JWT>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c</wsse:JWT>
  </wsse:Security>
</soap:Header>
<soap:Body>
  <soap:Fault>
  </soap:Fault>
</soap:Body>
</soap:Envelope>
local soap = require"soap"

ngx.req.read_body()
local req_body = ngx.req.get_body_data()  -- req_body is now a string of the SOAP POST payload.
local namespace, elem_name, elems = soap.decode(req_body)
--How to get SOAP HEADER VALUES?
local jwt = elems["SOAP:Header"].get("wsse:Security").get("wsse:JWT")

--Validate JWT next and if good continue

--Add back 2 extra SOAP Headers to the elements
elems["SOAP:Header"].get("wsse:Security").add("wsse:Username", "Bob")
elems["SOAP:Header"].get("wsse:Security").add("wsse:UserId", "sadfd-213213-dfsafds-234234")

ngx.req.set_body_data(soap.encode(namespace, elem_name, elems))

I may have to just use a Lua XML Parser on the body as a string and just go from there though.

tomasguisasola commented 6 years ago

Hi Jeremy

The headers are ignored in soap.decode(), but you can adapt it to collect the headers in a table (for instance) and return it to the caller as a fourth result. This will ensure compatibility with older versions. Similarly you can do the same with soap.encode() to accept headers in the arguments.

If you prefer, I could code that adaptions to you if you send me some samples of the original and modified SOAP documents. Actually I have some free time to do that.

Regards, Tomás

2018-05-28 16:44 GMT-03:00 jeremyjpj0916 notifications@github.com:

@tomasguisasola https://github.com/tomasguisasola Glad to see you are still active here on the repo 👍 ,

I think this lib will not work based on my other readings because you ignore SOAP:Header ? And the header is where all sorts of values tied to authn/authz happens in SOAP transactions which is what I need access to.

Yes in a way. Essentially in sudo code this is what I want to be able to do:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope/" soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c local soap = require"soap" ngx.req.read_body() local req_body = ngx.req.get_body_data() -- req_body is now a string of the SOAP POST payload. local namespace, elem_name, elems = soap.decode(req_body) --How to get SOAP HEADER VALUES? local jwt = elems["SOAP:Header"].get("wsse:Security").get("wsse:JWT") --Validate JWT next and if good continue --Add back 2 extra SOAP Headers to the elements elems["SOAP:Header"].get("wsse:Security").add("wsse:Username", "Bob") elems["SOAP:Header"].get("wsse:Security").add("wsse:UserId", "sadfd-213213-dfsafds-234234") ngx.req.set_body_data(soap.encode(namespace, elem_name, elems)) I may have to just use a Lua XML Parser on the body as a string and just go from there though. — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub , or mute the thread .
jeremyjpj0916 commented 6 years ago

@tomasguisasola If you have any time for it that would be awesome! I can report back and test the functionality you add if you change the logic and have some test case code I can copy for what it will look like to parse out header/add header values + re-encode.

Example Inbound SOAP:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Header>
    <wsse:Security>
     <wsse:JWT>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c</wsse:JWT>
    </wsse:Security>
  </soap:Header>
  <soap:Body>
    <searchClaims>
        <firstServiceDate>2015-03-19</firstServiceDate>
        <lastServiceDate>2015-03-19</lastServiceDate>
        <memSuffix>030303</memSuffix>
        <phsNumber>34343</phsNumber>
        <taxId>34525345325435342534523</taxId>
        <subNum>768787688678678768</subNum>
    </searchClaims>
  </soap:Body>
</soap:Envelope>

Example Modified Outbound SOAP after logic and validation:

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Header>
    <wsse:Security>
      <wsse:Username>MyConsumer</wsse:Username>
      <wsse:Userid>33333-33333-33333-33333</wsse:Userid>
    </wsse:Security>
  </soap:Header>
  <soap:Body>
    <searchClaims>
        <firstServiceDate>2015-03-19</firstServiceDate>
        <lastServiceDate>2015-03-19</lastServiceDate>
        <memSuffix>030303</memSuffix>
        <phsNumber>34343</phsNumber>
        <taxId>34525345325435342534523</taxId>
        <subNum>768787688678678768</subNum>
    </searchClaims>
  </soap:Body>
</soap:Envelope>

So your library needs a way to read out the SOAP header values like wsse:JWT as well as add/remove SOAP header values so when I go to encode again it can produce the modified payload.

Essentially to give you a bigger picture of what I am doing, I am just a dev playing around with Kong gateway community edition: https://github.com/Kong/kong and I intended to use your library to write an open source plugin for their application that provides WS-Security but rather than having to follow all the nuances of ws-security directly with saml's and salts and such I intend to pass a JWT token in the ws-security headers for Kong to validate who the app is and if they are allowed to call the service. This token gets validated and resolved to being a "Consumer" within the Kong application(Identify who the calling application is and if they are authorized to call the service). Then the back-end SOAP Service provider gets 2 new SOAP Headers of Consumer Name and Consumer Id added(by the Kong plugin using your lib). My hope is most client/server soap libraries are flexible enough to parse out the soap headers we establish like Username/UserId and JWT validation comes in all sorts of libraries so I really think it will help put a modern twist on an older protocol(SOAP). Interested to hear your thoughts on such a pattern if you have worked with SOAP plenty in the past and seen its pitfalls?

Other concerns I have with this lib are on case-sensitivity of the soap xml tags. Does your lib ignore case? I think that provides the best compatibility on payloads.

Thanks! -Jeremy