ACL doesn't work with multiple condition (beg_path AND

I have issue with my haproxy that running on my Ubuntu 16.04, i want to set static token to both environment on my server.

I am using path_beg and ssl_fc_sni

this is my config

frontend https
bind *:443 ssl crt /etc/ssl/mykey.pem

acl url_staging path_beg /123456
use_backend staging if { ssl_fc_sni staging.com AND url_staging }

acl url_production path_beg /789012
use_backend production if { ssl_fc_sni production.com AND url_production }

default_backend no-match

backend staging
    http-request set-path "%[path,regsub(^/123456/,/)]" # to remove the token after authenticated.
    server staging 127.0.0.1:4723

backend production
    http-request set-path "%[path,regsub(^/789012/,/)]" # to remove the token after authenticated.
    server production 127.0.0.1:4723

backend no-match  
    http-request deny deny_status 403

the problem is, when i try to visit production with staging token, it works and authenticated. production.com/123456 it will work, and vice versa.

acl staging hdr(Host) staging.com && path /123456

I did tried as per above, put both condition in the same ACL with AND expression but it getting worst, it was able to access without token.

What i want is, to authenticate staging with token/path staging which is 123456, and when i visit production must use production token/path. It should refuse when i hit endpoint production with token staging

so it will refuse connection when i try with production.com/123456.

HA-Proxy version 1.8.25-1

Thanks

Wrong statement, you need to close your anonymous ACL with }, instead you have that at the end.

Use:

acl url_staging path_beg /123456
use_backend staging if { ssl_fc_sni staging.com } AND url_staging

acl url_production path_beg /789012
use_backend production if { ssl_fc_sni production.com } AND url_production

And since AND is implicit, you can just:

acl url_staging path_beg /123456
use_backend staging if { ssl_fc_sni staging.com } url_staging

acl url_production path_beg /789012
use_backend production if { ssl_fc_sni production.com } url_production

Thanks. It works.

Anyway just want to check something with you.

You have mentioned that , AND is implicit, means that AND is default for multiple condition in HAproxy, or you referring to something else ?

Yes, that’s what I mean:

use_backend staging if { ssl_fc_sni staging.com } url_staging

is exactly the same as:

use_backend staging if { ssl_fc_sni staging.com } AND url_staging

Also see Using ACLs to form conditions.

@lukastribus Thanks for your explanation.

I was trying this ACL inline method with URI match cases, and it was not working on my HAproxy v2.6. Maybe because I’m using it with mixing multiple URIs and multiple DomainNames, but I’m not sure.

However, following is working fine for my case.

## Staging ACLs Rules
acl url_web_api_stg path_beg /web/api
acl url_portal_stg path_beg /portal
acl url_main_stg hdr(host) -i staging.com

use_backend be_82 if url_web_api_stg url_main_stg
use_backend be_83 if url_portal_stg url_main_stg
use_backend be_84 if url_main_stg

## Production ACLs Rules
acl url_web_api_prod path_beg /web/api
acl url_portal_prod path_beg /portal
acl url_main_prod hdr(host) -i production.com

use_backend be_85 if url_web_api_prod url_main_prod
use_backend be_86 if url_portal_prod url_main_prod
use_backend be_87 if url_main_prod

Still, I’m curious to know that why following inline acl rule-set is not working for me:

use_backend be_85 if { ssl_fc_sni production.com } url_web_api_prod
use_backend be_86 if { ssl_fc_sni production.com } url_portal_prod
use_backend be_87 if url_main_prod

instead of be_85 and be_86, it always sends the traffic to be_87, do I need to change the order?

Thanks

Do not use ssl_fc_sni when you can use the host header. You need to know TLS SNI behaviour inside out to not run into any corner cases.

That said, I don’t know the rest of your configuration, so it’s impossible for me to say if URI matching would even work.

If you are running in HTTP mode, use HTTP headers only for routing. For example:

use_backend be_85 if { hdr(host) -i production.com } url_web_api_prod

If it doesn’t work, start by trying to match just one condition and then find out which one of the conditions does not match.

The AND combination between different conditions is not a problem; single conditions very likely are.