Hi, As discussed today offline, a set of patches to allow VMODs to check IP addresses against named VCL ACLs.
Cheers, Dridi
From 024edb4e231f0ca4a213cb6e277fc577d9ee6d6f Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune <[email protected]> Date: Tue, 23 Feb 2016 16:22:34 +0100 Subject: [PATCH 1/5] Allow ACLs to be used outside of transactions --- bin/varnishd/cache/cache_vrt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c index 50a7232..a3a12fb 100644 --- a/bin/varnishd/cache/cache_vrt.c +++ b/bin/varnishd/cache/cache_vrt.c @@ -67,7 +67,9 @@ VRT_acl_log(VRT_CTX, const char *msg) { CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); - VSLb(ctx->vsl, SLT_VCL_acl, "%s", msg); + AN(msg); + if (ctx->vsl != NULL) + VSLb(ctx->vsl, SLT_VCL_acl, "%s", msg); } /*--------------------------------------------------------------------*/ -- 2.5.0
From 36677b9edd3c893bbdde75d97672ef7993c2fdac Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune <[email protected]> Date: Tue, 23 Feb 2016 16:39:24 +0100 Subject: [PATCH 2/5] Introduce a new ACL type for VMODs --- include/vrt.h | 8 ++++++++ lib/libvcc/vcc_acl.c | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/include/vrt.h b/include/vrt.h index c38fc59..ae5c6e8 100644 --- a/include/vrt.h +++ b/include/vrt.h @@ -53,6 +53,7 @@ /***********************************************************************/ struct VCL_conf; +struct vrt_acl; struct busyobj; struct director; struct http; @@ -70,6 +71,7 @@ struct ws; * (alphabetic order) */ +typedef const struct vrt_acl * VCL_ACL; typedef const struct director * VCL_BACKEND; typedef const struct vmod_priv * VCL_BLOB; typedef unsigned VCL_BOOL; @@ -240,6 +242,12 @@ struct vrt_ref { /* ACL related */ #define VRT_ACL_MAXADDR 16 /* max(IPv4, IPv6) */ +struct vrt_acl { + unsigned magic; +#define VRT_ACL_MAGIC 0x78329d96 + int (*match)(VRT_CTX, VCL_IP); +}; + void VRT_acl_log(VRT_CTX, const char *msg); /* req related */ diff --git a/lib/libvcc/vcc_acl.c b/lib/libvcc/vcc_acl.c index 78d9ec5..e1bfb1e 100644 --- a/lib/libvcc/vcc_acl.c +++ b/lib/libvcc/vcc_acl.c @@ -443,6 +443,15 @@ vcc_acl_emit(struct vcc *tl, const char *acln, int anon) if (!anon) Fh(tl, 0, "\tVRT_acl_log(ctx, \"NO_MATCH %s\");\n", acln); Fh(tl, 0, "\treturn (0);\n}\n"); + + if (anon) + return; + + /* Emit the struct that will be referenced */ + Fh(tl, 0, "\nconst struct vrt_acl vrt_acl_named_%s = {\n", acln); + Fh(tl, 0, "\t.magic = VRT_ACL_MAGIC,\n"); + Fh(tl, 0, "\t.match = &match_acl_named_%s,\n", acln); + Fh(tl, 0, "};\n\n"); } void -- 2.5.0
From 89dee1ce769a0814d6b7bb63c2d66651b4d47ea0 Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune <[email protected]> Date: Tue, 23 Feb 2016 17:55:13 +0100 Subject: [PATCH 3/5] Make named ACLs available to VMODs --- doc/sphinx/reference/vmod.rst | 6 +++++- lib/libvcc/vcc_acl.c | 15 +++++++++++---- lib/libvcc/vcc_compile.h | 1 + lib/libvcc/vcc_expr.c | 21 +++++++++++++++++++++ lib/libvcc/vmodtool.py | 1 + 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/doc/sphinx/reference/vmod.rst b/doc/sphinx/reference/vmod.rst index 40b7bf7..b77cafb 100644 --- a/doc/sphinx/reference/vmod.rst +++ b/doc/sphinx/reference/vmod.rst @@ -115,7 +115,11 @@ language representation. Here is a description of them. All but the PRIV and STRING_LIST types have typedefs: VCL_INT, VCL_REAL, etc. -.. TODO document ACL if patchwork #314 is merged +ACL + C-type: ``int(acl_f)(VRT_CTX, VCL_IP)*`` + + A function that checks an IP address against the named ACL declared in + VCL. BACKEND C-type: ``const struct director *`` diff --git a/lib/libvcc/vcc_acl.c b/lib/libvcc/vcc_acl.c index e1bfb1e..ca84140 100644 --- a/lib/libvcc/vcc_acl.c +++ b/lib/libvcc/vcc_acl.c @@ -474,7 +474,7 @@ void vcc_ParseAcl(struct vcc *tl) { struct token *an; - int i; + struct symbol *sym; char acln[1024]; vcc_NextToken(tl); @@ -490,13 +490,20 @@ vcc_ParseAcl(struct vcc *tl) an = tl->t; vcc_NextToken(tl); - i = vcc_AddDef(tl, an, SYM_ACL); - if (i > 1) { + bprintf(acln, "%.*s", PF(an)); + + sym = VCC_GetSymbolTok(tl, an, SYM_ACL); + AN(sym); + if (sym->ndef > 0) { VSB_printf(tl->sb, "ACL %.*s redefined\n", PF(an)); vcc_ErrWhere(tl, an); return; } - bprintf(acln, "%.*s", PF(an)); + sym->fmt = ACL; + sym->eval = vcc_Eval_Acl; + sym->eval_priv = TlDup(tl, acln); + sym->ndef++; + ERRCHK(tl); SkipToken(tl, '{'); diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h index 7816a3e..20bc18c 100644 --- a/lib/libvcc/vcc_compile.h +++ b/lib/libvcc/vcc_compile.h @@ -286,6 +286,7 @@ sym_expr_t vcc_Eval_Var; sym_expr_t vcc_Eval_SymFunc; void vcc_Eval_Func(struct vcc *tl, const char *cfunc, const char *extra, const char *name, const char *args); +sym_expr_t vcc_Eval_Acl; sym_expr_t vcc_Eval_Backend; sym_expr_t vcc_Eval_Probe; diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c index af3b3e7..f8fd0f5 100644 --- a/lib/libvcc/vcc_expr.c +++ b/lib/libvcc/vcc_expr.c @@ -494,10 +494,28 @@ vcc_Eval_BoolConst(struct vcc *tl, struct expr **e, const struct symbol *sym) */ void +vcc_Eval_Acl(struct vcc *tl, struct expr **e, const struct symbol *sym) +{ + + assert(sym->kind == SYM_ACL); + AN(sym->eval_priv); + + vcc_ExpectCid(tl); + vcc_AddRef(tl, tl->t, SYM_ACL); + *e = vcc_mk_expr(ACL, "&vrt_acl_named_%s", + (const char *)sym->eval_priv); + (*e)->constant = EXPR_VAR; /* XXX ? */ + vcc_NextToken(tl); +} +/*-------------------------------------------------------------------- + */ + +void vcc_Eval_Backend(struct vcc *tl, struct expr **e, const struct symbol *sym) { assert(sym->kind == SYM_BACKEND); + AN(sym->eval_priv); vcc_ExpectCid(tl); vcc_AddRef(tl, tl->t, SYM_BACKEND); @@ -819,6 +837,8 @@ vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt) * XXX: look for SYM_VAR first for consistency ? */ sym = NULL; + if (fmt == ACL) + sym = VCC_FindSymbol(tl, tl->t, SYM_ACL); if (fmt == BACKEND) sym = VCC_FindSymbol(tl, tl->t, SYM_BACKEND); if (fmt == PROBE) @@ -841,6 +861,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt) switch(sym->kind) { case SYM_VAR: case SYM_FUNC: + case SYM_ACL: case SYM_BACKEND: case SYM_PROBE: AN(sym->eval); diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py index bb29bd4..024d78a 100755 --- a/lib/libvcc/vmodtool.py +++ b/lib/libvcc/vmodtool.py @@ -46,6 +46,7 @@ from os.path import dirname, exists, join, realpath from pprint import pprint, pformat ctypes = { + 'ACL': "VCL_ACL", 'BACKEND': "VCL_BACKEND", 'BLOB': "VCL_BLOB", 'BOOL': "VCL_BOOL", -- 2.5.0
From 50270c4fde8dc55f8fd6f617b156b18f49bdfebc Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune <[email protected]> Date: Tue, 23 Feb 2016 18:26:08 +0100 Subject: [PATCH 4/5] Add a new VRT_acl_match function to the VMODs ABI VRT_MINOR_VERSION needs to be incremented for the 4.1 branch. --- bin/varnishd/cache/cache_vrt.c | 10 ++++++++++ include/vrt.h | 1 + 2 files changed, 11 insertions(+) diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c index a3a12fb..388b703 100644 --- a/bin/varnishd/cache/cache_vrt.c +++ b/bin/varnishd/cache/cache_vrt.c @@ -72,6 +72,16 @@ VRT_acl_log(VRT_CTX, const char *msg) VSLb(ctx->vsl, SLT_VCL_acl, "%s", msg); } +int +VRT_acl_match(VRT_CTX, VCL_ACL acl, VCL_IP ip) +{ + + CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); + CHECK_OBJ_NOTNULL(acl, VRT_ACL_MAGIC); + AN(ip); + return (acl->match(ctx, ip)); +} + /*--------------------------------------------------------------------*/ struct http * diff --git a/include/vrt.h b/include/vrt.h index ae5c6e8..6e10a86 100644 --- a/include/vrt.h +++ b/include/vrt.h @@ -249,6 +249,7 @@ struct vrt_acl { }; void VRT_acl_log(VRT_CTX, const char *msg); +int VRT_acl_match(VRT_CTX, VCL_ACL, VCL_IP); /* req related */ -- 2.5.0
From 878a2c24803496c2e4cddc14e13aab36f20ed648 Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune <[email protected]> Date: Tue, 23 Feb 2016 18:44:14 +0100 Subject: [PATCH 5/5] Test VMOD ACLs using vmod-debug --- bin/varnishtest/tests/m00023.vtc | 32 ++++++++++++++++++++++++++++++++ lib/libvmod_debug/vmod.vcc | 4 ++++ lib/libvmod_debug/vmod_debug.c | 11 +++++++++++ 3 files changed, 47 insertions(+) create mode 100644 bin/varnishtest/tests/m00023.vtc diff --git a/bin/varnishtest/tests/m00023.vtc b/bin/varnishtest/tests/m00023.vtc new file mode 100644 index 0000000..b45d5bf --- /dev/null +++ b/bin/varnishtest/tests/m00023.vtc @@ -0,0 +1,32 @@ +varnishtest "Test VMOD ACLs" + +varnish v1 -vcl { + import debug; + + backend dummy { + .host = "${bad_ip}"; + } + + acl loopback { + "127"/24; + } + + sub vcl_init { + if (!debug.match_acl(loopback, "127.0.0.127")) { + debug.init_fail(); + } + } + + sub vcl_recv { + if (debug.match_acl(loopback, client.ip)) { + return (synth(200)); + } + return (synth(500)); + } +} -start + +client c1 { + txreq + rxresp + expect resp.status == 200 +} -run diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc index d0ebe1c..1725689 100644 --- a/lib/libvmod_debug/vmod.vcc +++ b/lib/libvmod_debug/vmod.vcc @@ -150,3 +150,7 @@ Reset to the previous snapshot of a workspace, taken from debug.workspace_snap. $Function VOID vcl_release_delay(DURATION) Hold a reference to the VCL when it goes cold for the given delay. + +$Function BOOL match_acl(ACL acl, IP ip) + +Perform an IP match against a named ACL. diff --git a/lib/libvmod_debug/vmod_debug.c b/lib/libvmod_debug/vmod_debug.c index 1e1b71f..aa98732 100644 --- a/lib/libvmod_debug/vmod_debug.c +++ b/lib/libvmod_debug/vmod_debug.c @@ -466,3 +466,14 @@ vmod_vcl_release_delay(VRT_CTX, VCL_DURATION delay) assert(delay > 0.0); vcl_release_delay = delay; } + +VCL_BOOL +vmod_match_acl(VRT_CTX, VCL_ACL acl, VCL_IP ip) +{ + + CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC); + CHECK_OBJ_ORNULL(acl, VRT_ACL_MAGIC); + AN(ip); + + return (VRT_acl_match(ctx, acl, ip)); +} -- 2.5.0
_______________________________________________ varnish-dev mailing list [email protected] https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev
