Golang has great middleware functionality for endpoints that allows a person to readily secure all of them. I was wondering there would be anyway doing similar in BaseX for restxq & websockets. For example by requiring all requests to have a particular query parameter (very basic example). ... to protect say against browser / javascript port scanning.
Eg https://stackoverflow.com/questions/26204485/gorilla-mux-custom-middleware and check that request contains a particular parameter (very basic security)
It seems that I have to secure each endpoint individually.
Adam
Hi Adam,
You could have a loot at our Permissions layer [1]. It can be used for all kinds of checks, not only those specific to authentication. I think we should generalize the concept in a future version of BaseX and introduce additional post-hooks.
Hope this helps? Christian
[1] https://docs.basex.org/wiki/Permissions
On Mon, Jan 18, 2021 at 3:19 AM Adam Law adamjameslaw@gmail.com wrote:
Golang has great middleware functionality for endpoints that allows a person to readily secure all of them. I was wondering there would be anyway doing similar in BaseX for restxq & websockets. For example by requiring all requests to have a particular query parameter (very basic example). ... to protect say against browser / javascript port scanning.
Eg https://stackoverflow.com/questions/26204485/gorilla-mux-custom-middleware and check that request contains a particular parameter (very basic security)
It seems that I have to secure each endpoint individually.
Adam
Hi Christian,
Many thanks for your reply. Pre and Post Hooks would be great
Here is some crazy stuff I thought of (just a skeleton). It should allow say a code search for %((rest)|(ws)).*:((path)|(connect))to ensure that all endpoints have permissions middleware of some sort.
Hope it is not too silly.
Adam /--------------------------------- import module namespace authMiddleware = 'http://middleware..auth' at '[...].xqm'
declare
%rest:preHook:(authMiddleware:authoriseFail2BanRest):path("/main/admin"):result($vs_authKeyResult) %rest:postHook:(noCaching:noCacheFunc):(htmlTextConversion:text2HTMLFunc) %output:method("text") function local:admin($vs_authKeyResult) { let $authorized := 'Welcome to the admin page' let $unauthorized := 'Your IP has been logged with fail2ban' let $result := if ($vs_authKeyResult=true()) then $authorized else $unauthorized return $result };
declare
%ws:preHook:(authMiddleware:authoriseFail2BanWS):connect('/'):result($vs_authKeyResult) function local:connect($vs_authKeyResult) as empty-sequence() { let $id := ws:id() let $message := json:serialize(map { 'type': 'Connect', 'id': $id }) return if ($vs_authKeyResult=true()) then ws:broadcast($message) else () };
/--------------------------------- module namespace authMiddleware = 'http://middleware.auth';
import module namespace loggingMiddleware = 'http://middleware.logging' at '[...].xqm'
declare %preHook:(loggingMiddleware:functionLog):result($vs_logResult) (:a postHook here would be before the calling function local:admin :) %rest:query-param("vs_authKey", " {$vs_authKey}") function authMiddleware:authoriseFail2BanRest($vs_authKey,$vs_logResult) { let $result := if ($vs_authKey='YKJKhh') then true() else false() let $result := if ($vs_logResult='override') then true() else result() return $result };
/--------------------------------- module namespace loggingMiddleware = 'http://middleware.logging'; module namespace myUpdatingOutput = 'http://function.updatingOutput';
declare %rest:query-param("vs_logAside", " {$vs_logAside}") function loggingMiddleware:functionLog($vs_logAside) { let $result := if (vs_logAside != 'adminOverride*75x4558') then myUpdatingOutput:logwrite(request:remote-address()) else 'override' return $result };
More Silly
import module namespace authMiddleware = 'http://middleware..auth' at '[...].xqm'
declare
%rest:preHook:(authMiddleware:authoriseFail2BanRest:input("/main/admin",,)):path("/main/admin"):result($vs_authKeyResult) %rest:query-param("vbJson", " {$vbJson}") %if ($vbJSON = 'true') then %rest:postHook:(noCaching:noCacheFunc):(JSONConversion:xml2JOSNFunc:input($resultdifferent))
%output:method("xml") function local:admin($vs_authKeyResult) { let $authorized := 'Welcome to the admin page' let $unauthorized := 'Your IP has been logged with fail2ban' let $resultdifferent := if ($vs_authKeyResult=true()) then <jsonRep>{$authorized}</jsonRep> else <jsonRep>{$unauthorized}</jsonRep>{ return <xml>{$resultdifferent/*}</xml> };
/--------------------------------- module namespace authMiddleware = 'http://middleware.auth';
import module namespace loggingMiddleware = 'http://middleware.logging' at '[...].xqm'
declare %variable $vsPath external = "/"; %rest:query-param("vs_logAside", " {$vs_logAside}") %preHook:(loggingMiddleware:functionLog:input($vsPath,$vs_logAside)):result($vs_logResult) (:a postHook here would be before the calling function local:admin :) %rest:query-param("vs_authKey", " {$vs_authKey}") function authMiddleware:authoriseFail2BanRest($vsPath,$vs_authKey,$vs_logResult) { let $result := if ($vs_authKey='YKJKhh') then true() else false() let $result := if ($vs_logResult='override') then true() else result() return $result };
/--------------------------------- module namespace loggingMiddleware = 'http://middleware.logging'; module namespace myUpdatingOutput = 'http://function.updatingOutput'; declare %variable $vsPath external = "/"; %variable $vs_logAside external = "/"; function loggingMiddleware:functionLog($vsPath,$vs_logAside) { let $result := if (vs_logAside != 'adminOverride*75x4558') then myUpdatingOutput:logwrite($vsPath,request:remote-address()) else 'override' return $result };
Another thought - a 'catch all' path for fail2ban to catch attempted accessess to undefined paths. I haven't tested this to see if there is such a thing in BaseX https://stackoverflow.com/questions/50282541/catch-all-url-in-golang
On Mon, Jan 18, 2021 at 5:26 PM Christian Grün christian.gruen@gmail.com wrote:
Hi Adam,
You could have a loot at our Permissions layer [1]. It can be used for all kinds of checks, not only those specific to authentication. I think we should generalize the concept in a future version of BaseX and introduce additional post-hooks.
Hope this helps? Christian
[1] https://docs.basex.org/wiki/Permissions
On Mon, Jan 18, 2021 at 3:19 AM Adam Law adamjameslaw@gmail.com wrote:
Golang has great middleware functionality for endpoints that allows a
person to readily secure all of them. I was wondering there would be anyway doing similar in BaseX for restxq & websockets. For example by requiring all requests to have a particular query parameter (very basic example). ... to protect say against browser / javascript port scanning.
Eg
https://stackoverflow.com/questions/26204485/gorilla-mux-custom-middleware and check that request contains a particular parameter (very basic security)
It seems that I have to secure each endpoint individually.
Adam
You could have a look at the "Catch HTTP Errors" section in our documentation.
[1] https://docs.basex.org/wiki/RESTXQ#Error_Handling
On Mon, Jan 18, 2021 at 1:30 PM Adam Law adamjameslaw@gmail.com wrote:
Another thought - a 'catch all' path for fail2ban to catch attempted accessess to undefined paths. I haven't tested this to see if there is such a thing in BaseX https://stackoverflow.com/questions/50282541/catch-all-url-in-golang
On Mon, Jan 18, 2021 at 5:26 PM Christian Grün christian.gruen@gmail.com wrote:
Hi Adam,
You could have a loot at our Permissions layer [1]. It can be used for all kinds of checks, not only those specific to authentication. I think we should generalize the concept in a future version of BaseX and introduce additional post-hooks.
Hope this helps? Christian
[1] https://docs.basex.org/wiki/Permissions
On Mon, Jan 18, 2021 at 3:19 AM Adam Law adamjameslaw@gmail.com wrote:
Golang has great middleware functionality for endpoints that allows a person to readily secure all of them. I was wondering there would be anyway doing similar in BaseX for restxq & websockets. For example by requiring all requests to have a particular query parameter (very basic example). ... to protect say against browser / javascript port scanning.
Eg https://stackoverflow.com/questions/26204485/gorilla-mux-custom-middleware and check that request contains a particular parameter (very basic security)
It seems that I have to secure each endpoint individually.
Adam
basex-talk@mailman.uni-konstanz.de