Re: How to debug matching ACLs?

2020-07-24 Thread Willy Tarreau
Hello Ricardo,

On Fri, Jul 24, 2020 at 10:36:59AM +0200, Ricardo Fraile wrote:
(...)
> I think that the "set-var" way is more flexible, as you can combine it with
> any other variable that helps to identify the client request. The proposed
> "here" converter can helps more.

OK, I'll try to think about it more.

> As an idea, it would be nice if these debug modifications done over the ACLs
> can be logged based on a condition, for example only with a particular
> client pattern, something like:
> 
>acl client_debug hdr_sub(User-Agent) client1-user-agent
>log-format %ci,%[var(txn.last_expr)] if client_debug

You cannot condition a log format versus another one, but what you can
do is use an intermediary variable:

acl client_debug hdr_sub(User-Agent) client1-user-agent
http-request ser-var(txn.debug_expr) var(txn.last_expr) if client_debug
log-format %ci,%[var(txn.debug_expr)]

=> your debug_expr variable will only be set if client_debug is true,
otherwise it will log an empty string.

Willy



Re: How to debug matching ACLs?

2020-07-24 Thread Ricardo Fraile

Hello Willy,


Following your suggestions, I've been testing the "debug" solution (in a 
2.2 HAproxy) with this sample conf:


   http-request use-service prometheus-exporter if { path,debug(buf0) -m 
beg /metrics }


seeing from the socket the entries registered on buf0:

   # echo "show events buf0" | socat stdio /var/run/haproxy.sock
   <0>2020-07-24T09:24:19.598250+02:00 [debug] buf0: type=str 
   <0>2020-07-24T09:24:26.981110+02:00 [debug] buf0: type=str 
   <0>2020-07-24T09:24:34.598446+02:00 [debug] buf0: type=str 


Later on, the same http condition, but now with "set-var":

   http-request use-service prometheus-exporter if { 
path,set-var(txn.last_expr) -m beg /metrics }

   log-format %ci,%[var(txn.last_expr)]

and seeing the lines on the logs:

   Jul 24 09:33:49 server1 haproxy[10291]: 192.168.1.17,/metrics
   Jul 24 09:34:04 server1 haproxy[10291]: 192.168.1.17,/metrics


I think that the "set-var" way is more flexible, as you can combine it 
with any other variable that helps to identify the client request. The 
proposed "here" converter can helps more.



As an idea, it would be nice if these debug modifications done over the 
ACLs can be logged based on a condition, for example only with a 
particular client pattern, something like:


   acl client_debug hdr_sub(User-Agent) client1-user-agent
   log-format %ci,%[var(txn.last_expr)] if client_debug


Thanks for your detailed explanations,



Re: How to debug matching ACLs?

2020-07-23 Thread Willy Tarreau
Hello Ricardo,

On Thu, Jul 23, 2020 at 05:52:55PM +0200, Ricardo Fraile wrote:
> Hello,
> 
> On a complex configuration with multiples ACLs, is there a way to debug what
> of them are applied over a request?

Depending how you write them (and what version you are using), you may
be able to use the "debug" converter at the end of the expression to
capture the value and send it to a ring buffer that you can consult
elsewhere. You can also copy a value into a variable that you append
in the log.

> Is it possible to append the unique id of the ACLs to the line on the log?

Not really, the problem is that there isn't a single set of ACL, but a large
set which apply to many actions. I've seen configurations evaluating up to
6000 ACLs per request, it's definitely not even realistic to log anything
in such a mess. And there's no real "this use case is more common, let's
focus on it only" because there are many rulesets. In addition, anonymous
ACLs are fairly common, and sometimes more readable.

Cyril Bonté had worked on such a solution many years ago. By then we had
very few rulesets, and as we were adding new ones with many ACLs evaluated
for a single request, it quickly became difficult to exploit.

That's why I really encourage you to instead set a variable and log it.
There's even a "set-var" converter that duplicates the expression's
value into a variable. Thus for example, instead of doing :

   use_backend foo if { path_beg /foo }

You could do:

   use_backend foo if { path,set-var(txn.last_expr) -m beg /foo }

And log "var(txn.last_expr)" to always get the last evaluated ACL among
those you have instrumented.

This makes me think that it could be convenient to have a new converter
called "here" that, just like set-var() or debug(), passes the value and
stores the current config file's line number into a fixed variable so
that you could have it present in your logs.

You could then do something like:

   use_backend foo if { path,here -m beg /foo }

If you'd place them on all final rules, you could easily detect what
rule was the one taking the final decision (redirect, deny, return,
etc). I suspect that we'd need a few sets, though (tcp-request,
http-request, tcp-response, http-response, use_backend, use-server).
But maybe in this case storing a history of the last 3-10 "here"
would help.

Note however that this would only be useful to know that a rule was
evaluated last. It doesn't guarantee that it matched, but if placed
on a final rule it will be reliable enough.

Hoping this helps, feel free to fuel the discussion with more ideas!

Willy



How to debug matching ACLs?

2020-07-23 Thread Ricardo Fraile

Hello,

On a complex configuration with multiples ACLs, is there a way to debug 
what of them are applied over a request?


Is it possible to append the unique id of the ACLs to the line on the 
log?



Thanks,