]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR/DOC: spoe-server: Add documentation
authorThierry FOURNIER <thierry.fournier@ozon.io>
Sun, 25 Feb 2018 20:28:05 +0000 (21:28 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 13 May 2019 15:43:47 +0000 (17:43 +0200)
This is the documentation and examples.

contrib/spoa_server/README
contrib/spoa_server/print_r.lua [new file with mode: 0644]
contrib/spoa_server/ps_lua.lua [new file with mode: 0644]
contrib/spoa_server/ps_python.py [new file with mode: 0644]
contrib/spoa_server/spoa-server.conf [new file with mode: 0644]
contrib/spoa_server/spoa-server.spoe.conf [new file with mode: 0644]

index 7e376ee1d6b856f6b70f8ba0968a548e1fcba770..57ec9c414dacac98fa8720203c56d68b41495753 100644 (file)
@@ -1,10 +1,18 @@
-A Random IP reputation service acting as a Stream Processing Offload Agent
---------------------------------------------------------------------------
+Multi script langyage Stream Processing Offload Agent
+-----------------------------------------------------
 
-This is a very simple service that implement a "random" ip reputation
-service. It will return random scores for all checked IP addresses. It only
-shows you how to implement a ip reputation service or such kind of services
-using the SPOE.
+This agent receive SPOP message and process it with script languages. The
+language register callback with a message. Each callback receive the list
+of arguments with types according with the language capabilities. The
+callback write variables which are sent as response when the processing
+is done.
+
+
+  Compilation
+---------------
+
+Actually, the server support Lua and Python. Type "make" with the options:
+USE_LUA=1 and/or USE_PYTHON=1.
 
 
   Start the service
@@ -19,70 +27,47 @@ binary:
         -d                  Enable the debug mode
         -p <port>           Specify the port to listen on (default: 12345)
         -n <num-workers>    Specify the number of workers (default: 5)
+        -f <file>           Load script according with the supported languages
 
-Note: A worker is a thread.
-
-
-  Configure a SPOE to use the service
----------------------------------------
-
-All information about SPOE configuration can be found in "doc/SPOE.txt". Here is
-the configuration template to use for your SPOE:
-
-    [ip-reputation]
-
-    spoe-agent iprep-agent
-        messages check-client-ip
-
-        option var-prefix iprep
-
-        timeout hello      100ms
-        timeout idle       30s
-        timeout processing 15ms
-
-        use-backend iprep-backend
+The file processor is recognized using the extension. .lua or .luac for lua and
+.py for python. Start example:
 
-    spoe-message check-client-ip
-        args src
-        event on-client-session
+    $> ./spoa -d -f ps_lua.lua
 
+        $> ./spoa -d -f ps_pyhton.py
 
-The engine is in the scope "ip-reputation". So to enable it, you must set the
-following line in a frontend/listener section:
 
-    frontend my-front
-        ...
-        filter spoe engine ip-reputation config /path/spoe-ip-reputation.conf
-       ....
+  Configure
+-------------
 
-where "/path/spoe-ip-reputation.conf" is the path to your SPOE configuration
-file. The engine name is important here, it must be the same than the one used
-in the SPOE configuration file.
+Sample configuration are join to this server:
 
-IMPORTANT NOTE:
-    Because we want to send a message on the "on-client-session" event, this
-    SPOE must be attached to a proxy with the frontend capability. If it is
-    declared in a backend section, it will have no effet.
+  spoa-server.conf      : The HAProxy configuration file using SPOE server
+  spoa-server.spoe.conf : The SPOP description file used by HAProxy
+  ps_lua.lua            : Processing Lua example
+  ps_python.py          : Processing Python example
 
 
-Because, in SPOE configuration file, we declare to use the backend
-"iprep-backend" to communicate with the service, you must define it in HAProxy
-configuration. For example:
+  Considerations
+------------------
 
-    backend iprep-backend
-        mode tcp
-       timeout server 1m
-       server iprep-srv 127.0.0.1:12345 check maxconn 5
+This server is a beta version. It works fine, but some improvement will be
+welcome:
 
+Main process:
 
-In reply to the "check-client-ip" message, this service will set the variable
-"ip_score" for the session, an integer between 0 and 100. If unchanged, the
-variable prefix is "iprep". So the full variable name will be
-"sess.iprep.ip_score".
+ * Improve log management: Today the log are sent on stdout.
+ * Improve process management: The dead process are ignored.
+ * Implement systemd integration.
+ * Implement threads: It would be fine to implement thread working. Shared
+   memory is welcome for managing database connection pool and something like
+   that.
+ * Add PHP support and some other languages.
 
-You can use it in ACLs to experiment the SPOE feature. For example:
+Python:
 
-    tcp-request content reject if { var(sess.iprep.ip_score) -m int lt 20 }
+ * Improve repporting: Catch python error message and repport it in the right
+   place. Today the error are dumped on stdout. How using syslog for logging
+   stack traces ?
 
-With this rule, all IP address with a score lower than 20 will be rejected
-(Remember, this score is random).
+Maybe some other things...
diff --git a/contrib/spoa_server/print_r.lua b/contrib/spoa_server/print_r.lua
new file mode 100644 (file)
index 0000000..2fa57e7
--- /dev/null
@@ -0,0 +1,68 @@
+function color(index, str)
+       return "\x1b[" .. index .. "m" .. str .. "\x1b[00m"
+end
+
+function nocolor(index, str)
+       return str
+end
+
+function sp(count)
+       local spaces = ""
+       while count > 0 do
+               spaces = spaces .. "    "
+               count = count - 1
+       end
+       return spaces
+end
+
+function print_rr(p, indent, c, wr)
+       local i = 0
+       local nl = ""
+
+       if type(p) == "table" then
+               wr(c("33", "(table)") .. " " .. c("34", tostring(p)) .. " [")
+
+               mt = getmetatable(p)
+               if mt ~= nil then
+                       wr("\n" .. sp(indent+1) .. c("31", "METATABLE") .. ": ")
+                       print_rr(mt, indent+1, c, wr)
+               end
+
+               for k,v in pairs(p) do
+                       if i > 0 then
+                               nl = "\n"
+                       else
+                               wr("\n")
+                       end
+                       wr(nl .. sp(indent+1))
+                       if type(k) == "number" then
+                               wr(c("32", tostring(k)))
+                       else
+                               wr("\"" .. c("32", tostring(k)) .. "\"")
+                       end
+                       wr(": ")
+                       print_rr(v, indent+1, c, wr)
+                       i = i + 1
+               end
+               if i == 0 then
+                       wr(" " .. c("35", "/* empty */") .. " ]")
+               else
+                       wr("\n" .. sp(indent) .. "]")
+               end
+       elseif type(p) == "string" then
+               wr(c("33", "(string)") .. " \"" .. c("34", p) .. "\"")
+       else
+               wr(c("33", "(" .. type(p) .. ")") .. " " .. c("34", tostring(p)))
+       end
+end
+
+function print_r(p, col, wr)
+       if col == nil then col = true end
+       if wr == nil then wr = function(msg) io.stdout:write(msg) end end
+       if col == true then
+               print_rr(p, 0, color, wr)
+       else
+               print_rr(p, 0, nocolor, wr)
+       end
+       wr("\n")
+end
diff --git a/contrib/spoa_server/ps_lua.lua b/contrib/spoa_server/ps_lua.lua
new file mode 100644 (file)
index 0000000..2662045
--- /dev/null
@@ -0,0 +1,17 @@
+require("print_r")
+
+print_r("Load lua message processors")
+
+spoa.register_message("check-client-ip", function(args)
+       print_r(args)
+       spoa.set_var_null("null", spoa.scope.txn)
+       spoa.set_var_boolean("boolean", spoa.scope.txn, true)
+       spoa.set_var_int32("int32", spoa.scope.txn, 1234)
+       spoa.set_var_uint32("uint32", spoa.scope.txn, 1234)
+       spoa.set_var_int64("int64", spoa.scope.txn, 1234)
+       spoa.set_var_uint64("uint64", spoa.scope.txn, 1234)
+       spoa.set_var_ipv4("ipv4", spoa.scope.txn, "127.0.0.1")
+       spoa.set_var_ipv6("ipv6", spoa.scope.txn, "1::f")
+       spoa.set_var_str("str", spoa.scope.txn, "1::f")
+       spoa.set_var_bin("bin", spoa.scope.txn, "1::f")
+end)
diff --git a/contrib/spoa_server/ps_python.py b/contrib/spoa_server/ps_python.py
new file mode 100644 (file)
index 0000000..108eb48
--- /dev/null
@@ -0,0 +1,20 @@
+from pprint import pprint
+import spoa
+import ipaddress
+
+def check_client_ip(args):
+       pprint(args)
+       spoa.set_var_null("null", spoa.scope_txn)
+       spoa.set_var_boolean("boolean", spoa.scope_txn, True)
+       spoa.set_var_int32("int32", spoa.scope_txn, 1234)
+       spoa.set_var_uint32("uint32", spoa.scope_txn, 1234)
+       spoa.set_var_int64("int64", spoa.scope_txn, 1234)
+       spoa.set_var_uint64("uint64", spoa.scope_txn, 1234)
+       spoa.set_var_ipv4("ipv4", spoa.scope_txn, ipaddress.IPv4Address(u"127.0.0.1"))
+       spoa.set_var_ipv6("ipv6", spoa.scope_txn, ipaddress.IPv6Address(u"1::f"))
+       spoa.set_var_str("str", spoa.scope_txn, "1::f")
+       spoa.set_var_bin("bin", spoa.scope_txn, "1:\x01:\x02f\x00\x00")
+       return
+
+
+spoa.register_message("check-client-ip", check_client_ip)
diff --git a/contrib/spoa_server/spoa-server.conf b/contrib/spoa_server/spoa-server.conf
new file mode 100644 (file)
index 0000000..13bd126
--- /dev/null
@@ -0,0 +1,33 @@
+global
+       debug
+
+defaults
+       mode http
+       option httplog
+       option dontlognull
+       timeout connect 5000
+       timeout client 5000
+       timeout server 5000
+
+listen test
+       mode http
+       bind :10001
+       filter spoe engine spoa-server config spoa-server.spoe.conf
+       http-request set-var(req.a) var(txn.iprep.null),debug
+       http-request set-var(req.a) var(txn.iprep.boolean),debug
+       http-request set-var(req.a) var(txn.iprep.int32),debug
+       http-request set-var(req.a) var(txn.iprep.uint32),debug
+       http-request set-var(req.a) var(txn.iprep.int64),debug
+       http-request set-var(req.a) var(txn.iprep.uint64),debug
+       http-request set-var(req.a) var(txn.iprep.ipv4),debug
+       http-request set-var(req.a) var(txn.iprep.ipv6),debug
+       http-request set-var(req.a) var(txn.iprep.str),debug
+       http-request set-var(req.a) var(txn.iprep.bin),debug
+       http-request redirect location /%[var(sess.iprep.ip_score)]
+
+backend spoe-server
+       mode tcp
+       balance roundrobin
+       timeout connect 5s
+       timeout server  3m
+       server spoe-server 127.0.0.1:12345
diff --git a/contrib/spoa_server/spoa-server.spoe.conf b/contrib/spoa_server/spoa-server.spoe.conf
new file mode 100644 (file)
index 0000000..dab4e5a
--- /dev/null
@@ -0,0 +1,13 @@
+[spoa-server]
+
+spoe-agent spoa-server
+       messages check-client-ip
+       option var-prefix  iprep
+       timeout hello      100ms
+       timeout idle       30s
+       timeout processing 15ms
+       use-backend spoe-server
+
+spoe-message check-client-ip
+       args always_true int(1234) src ipv6(::55) req.fhdr(host)
+       event on-frontend-http-request