WebSEAL LUA http transformation rule for logging
This is a small follow-up post to my previous post on LUA transformation rules to retrieve external data WebSEAL LUA http transformation rules with external data
A blog post by my colleague got me thinking that we could use the LUA transformation rules for logging to REST logging systems: https://www.hansvandeweghe.com/2020/05/05/send-infomap-events-to-qradar/
So let’s try this out!
Since I don’t have a QRadar installation handy, I’m using Loggly here. The events are sent using HTTP POST in both cases, so it’s likely that you can exchange the Loggly endpoint with a QRadar endpoint.
Loggly
I’ve registered for a trial account at Loggly https://www.loggly.com/, since that seemed to be the fastest way to get a logging http endpoint up and running.
The HTTP/HTTPS event logger can be accessed by urls like this:
curl -H "content-type:text/plain" -d "Hello" http://logs-01.loggly.com/inputs/<TOKEN>/tag/http/
The <TOKEN>
is linked to your account, so private.
Note that this is a HTTP POST request.
Transformation rule with http.requests
You can edit the loguri
parameter to point to your own personal loggly account. Replace the <TOKEN>
with your personal token.
Save the script in the current directory as logglylua
(for the test)
local request = require "http.request"
local cjson = require "cjson"
local http_headers = require "http.headers"
local r = assert(request.new_from_uri("http://logs-01.loggly.com/inputs/<TOKEN>/tag/isva/"))
r.headers:upsert(":method", "POST")
r.headers:upsert("content-type", "application/json")
assert(r:set_body('{"url": "'..HTTPRequest.getURL()..'", "username": "'..Session.getUsername()..'"}'))
local h, res = assert(r:go())
Control.trace(5, res:get_body_as_string())
So this transformation rule will send the URL and the username to the http logging endpoint. Note that this is only a proof of concept, you’d need to verify that there is an authenticated session (otherwise the lua script will throw an error).
Examples for lua
The http-request
modules are included with ISVA 10.0.4+, but it’s a bit difficult to find examples.
The source on Github https://github.com/daurnimator/lua-http actually contains the best examples.
Test the rule
Prepare context.yaml
You can generate a context.yaml using dumpContext
(in lua script), or by creating one yourself.
See this blog post on how to do that : WebSEAL LUA http transformation rules with external data,
or check the official documentation.
I’m using this example context:
http:
request:
method: "GET"
url: "/junction1/index.html"
headers:
- name: "User-Agent"
value: "curl"
- name: "Host"
value: "www.ibm.com"
session:
username: "testuser"
credential:
attribute:
- name: "AZN_CRED_PRINCIPAL_NAME"
value: "testuser"
Run the test
You should now have 2 files in the current directory:
- loggly.lua ( the actual lua script )
- context.yaml (the webseal context)
podman run --rm -v ${PWD}:/lua_test:z --entrypoint iag_lua_transformation_test \
icr.io/ibmappgateway/ibm-application-gateway:22.07 -c /lua_test/context.yaml -s /lua_test/loggly.lua
Note: in podman, the :z
option in the volume mount seems necessary. The error message is not particularly helpful, but if you get the message below, it’s likely the volume mount files are not accessible by the container.
DPWWA3301E A failure occurred while parsing the YAML file: /var/iag/staging/context.yaml (bad file)
The reason is that the files actually should have system_u:object_r:container_file_t:s0
as selinux context. If you run the above podman command once with the :z option, the selinux context is updated and :z is no longer necessary.
If all goes well, you get this output in the cli.
Lua trace (level: 5): {"response" : "ok"}
In Loggly, it will look like something like this:
Notice that the json message that we sent in the LUA rule, is parsed in separate fields.
WebSeal configuration
webseald.conf
Once you’ve tested the rule, you can deploy it in WebSEAL.
Edit the webseald.conf, and add a request-match
entry.
This example is similar to the logging similar to the blogpost by Hans (to log AAC authentication)
loghttp = loggly.lua
[http-transformations:loghttp]
request-match = request:* /mga/*