@@ -231,6 +231,8 @@ public function doAction()
231231 foreach ($ item ['spec ' ]['rules ' ] as $ ruleKey => $ rule ) {
232232 $ aclName = $ frontend ['name ' ].'-rule- ' .$ ruleKey ;
233233 $ host = $ rule ['host ' ];
234+ //$host = "*.${host}"; // for testing purposes only
235+ //$host = ""; // for testing purposes only
234236 if (!$ this ->shouldCreateRule ($ rule )) {
235237 continue ;
236238 }
@@ -258,12 +260,76 @@ public function doAction()
258260 // ssl_fc_sni (this can be used only with type http)
259261 switch ($ sharedFrontend ['type ' ]) {
260262 case "http " :
261- $ acl ['value ' ] = "hdr(host) -i $ {host} path_beg -i $ {path}" ;
263+ // https://kubernetes.io/docs/concepts/services-networking/ingress/#hostname-wildcards
264+ // https://serverfault.com/questions/388937/how-do-i-match-a-wildcard-host-in-acl-lists-in-haproxy
265+ $ hostACL = "" ;
266+ if (substr ($ host , 0 , 2 ) == "*. " ) {
267+ // hdr(host) -m reg -i ^[^\.]+\.example\.org$
268+ // hdr(host) -m reg -i ^[^\.]+\.example\.org(:[0-9]+)?$
269+ $ hostACL = "hdr(host) -m reg -i ^[^\.]+ " .str_replace (". " , "\. " , substr ($ host , 1 ))."(:[0-9]+)?$ " ;
270+ } else {
271+ $ hostACL = "hdr(host) -m reg -i ^ " .str_replace (". " , "\. " , $ host )."(:[0-9]+)?$ " ;
272+ }
273+
274+ // https://kubernetes.io/docs/concepts/services-networking/ingress/#path-types
275+ // https://www.haproxy.com/documentation/hapee/latest/configuration/acls/syntax/
276+ $ pathType = $ path ['pathType ' ] ?? null ;
277+ $ pathACL = "" ;
278+ switch ($ pathType ) {
279+ case "Exact " :
280+ /**
281+ * Matches the URL path exactly and with case sensitivity.
282+ */
283+ $ pathACL = "path -m str $ {path}" ;
284+ break ;
285+ case "Prefix " :
286+ /**
287+ * Matches based on a URL path prefix split by /.
288+ * Matching is case sensitive and done on a path element by element basis.
289+ * A path element refers to the list of labels in the path split by the / separator.
290+ * A request is a match for path p if every p is an element-wise prefix of p of the request path.
291+ */
292+ $ pathACL = "path -m beg $ {path}" ;
293+ break ;
294+ case "ImplementationSpecific " :
295+ /**
296+ * With this path type, matching is up to the IngressClass.
297+ * Implementations can treat this as a separate pathType or treat it identically to Prefix or Exact path types.
298+ */
299+ $ pathACL = "path -m beg $ {path}" ;
300+ break ;
301+ default :
302+ $ pathACL = "path -m beg $ {path}" ;
303+ break ;
304+ }
305+
306+ if (empty ($ host )) {
307+ $ hostACL = "" ;
308+ }
309+ $ acl ['value ' ] = trim ("$ {hostACL} $ {pathACL}" );
262310 $ frontend ['ha_acls ' ]['item ' ][] = $ acl ;
263311 break ;
264312 case "https " :
265313 $ this ->log ("WARN unexpected behavior may occur when using a shared frontend of type https, path-based routing will not work " );
266- $ acl ['value ' ] = "req_ssl_sni -i $ {host}" ;
314+
315+ // https://kubernetes.io/docs/concepts/services-networking/ingress/#hostname-wildcards
316+ // https://serverfault.com/questions/388937/how-do-i-match-a-wildcard-host-in-acl-lists-in-haproxy
317+ $ hostACL = "" ;
318+ if (substr ($ host , 0 , 2 ) == "*. " ) {
319+ // hdr(host) -m reg -i ^[^\.]+\.example\.org$
320+ // hdr(host) -m reg -i ^[^\.]+\.example\.org(:[0-9]+)?$
321+ // sni should never have the port on the end as the host header may have
322+ $ hostACL = "req_ssl_sni -m reg -i ^[^\.]+ " .str_replace (". " , "\. " , substr ($ host , 1 ));
323+ } else {
324+ $ hostACL = "req_ssl_sni -m str -i $ {host}" ; // exact match case-insensitive
325+ }
326+
327+ if (empty ($ host )) {
328+ $ hostACL = "" ;
329+ $ this ->log ("WARN cannot create rule for $ {frontendName} because host is required for parent frontends of type: " .$ sharedFrontend ['type ' ]);
330+ continue 3 ;
331+ }
332+ $ acl ['value ' ] = trim ("$ {hostACL}" );
267333 $ frontend ['ha_acls ' ]['item ' ][] = $ acl ;
268334 break ;
269335 default :
0 commit comments