Follow-up on the ACL patch after an initial review, the test case doesn't lazily panic on failure.
Dridi
From 54609509f2d0f2631c6ad021818124e87e37b687 Mon Sep 17 00:00:00 2001 From: Dridi Boukelmoune <[email protected]> Date: Thu, 18 Jun 2015 19:00:09 +0200 Subject: [PATCH] Allow ACL references in VMODs Only log ACL results when the check happens during a transaction. VMOD writers can still build a context if they want to log ACL checks outside of a transaction. The VCL-to-C type correspondance currently relies on fragile code parsing and generation. ACLs are exposed as functions, and have a 2-step declaration in `vrt.h`. It could also be implemented with a miniobj and a new VRT function instead, but it requires heavier changes in libvcc. --- bin/varnishd/cache/cache_vrt.c | 6 ++++-- bin/varnishtest/tests/m00023.vtc | 32 ++++++++++++++++++++++++++++++++ doc/sphinx/reference/vmod.rst | 6 +++++- include/vrt.h | 9 +++++++-- lib/libvcc/vcc_acl.c | 17 ++++++++++++----- lib/libvcc/vcc_compile.h | 1 + lib/libvcc/vcc_expr.c | 21 +++++++++++++++++++++ lib/libvcc/vmodtool.py | 1 + lib/libvmod_debug/vmod.vcc | 4 ++++ lib/libvmod_debug/vmod_debug.c | 10 ++++++++++ 10 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 bin/varnishtest/tests/m00023.vtc diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c index 814d4af..200b4f8 100644 --- a/bin/varnishd/cache/cache_vrt.c +++ b/bin/varnishd/cache/cache_vrt.c @@ -66,8 +66,10 @@ void VRT_acl_log(VRT_CTX, const char *msg) { - CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); - VSLb(ctx->vsl, SLT_VCL_acl, "%s", msg); + CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC); + AN(msg); + if (ctx != NULL && ctx->vsl != NULL) + VSLb(ctx->vsl, SLT_VCL_acl, "%s", msg); } /*--------------------------------------------------------------------*/ diff --git a/bin/varnishtest/tests/m00023.vtc b/bin/varnishtest/tests/m00023.vtc new file mode 100644 index 0000000..062e30b --- /dev/null +++ b/bin/varnishtest/tests/m00023.vtc @@ -0,0 +1,32 @@ +varnishtest "Test VMOD ACLs" + +varnish v1 -vcl { + import ${vmod_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/doc/sphinx/reference/vmod.rst b/doc/sphinx/reference/vmod.rst index 0446e83..aed1e7a 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/include/vrt.h b/include/vrt.h index 4b429dd..991ac92 100644 --- a/include/vrt.h +++ b/include/vrt.h @@ -54,13 +54,17 @@ struct busyobj; struct director; struct http; struct req; +struct sess; struct suckaddr; struct vcl; +struct vrt_ctx; struct vmod; struct vsb; struct vsl_log; struct ws; +#define VRT_CTX const struct vrt_ctx *ctx + /*********************************************************************** * This is the central definition of the mapping from VCL types to * C-types. The python scripts read these from here. @@ -83,6 +87,9 @@ typedef const char * VCL_STRING; typedef double VCL_TIME; typedef void VCL_VOID; +typedef int (acl_f) (VRT_CTX, VCL_IP /* hack */ ); +typedef acl_f * VCL_ACL; + /*********************************************************************** * This is the composite argument we pass to compiled VCL and VRT * functions. @@ -119,8 +126,6 @@ struct vrt_ctx { void *specific; }; -#define VRT_CTX const struct vrt_ctx *ctx - /***********************************************************************/ struct vmod_data { diff --git a/lib/libvcc/vcc_acl.c b/lib/libvcc/vcc_acl.c index 72dd304..15264be 100644 --- a/lib/libvcc/vcc_acl.c +++ b/lib/libvcc/vcc_acl.c @@ -352,7 +352,7 @@ vcc_acl_emit(struct vcc *tl, const char *acln, int anon) struct token *t; struct inifin *ifp; - Fh(tl, 0, "\nstatic int\n"); + Fh(tl, 0, "\nstatic int __match_proto__(acl_f)\n"); Fh(tl, 0, "match_acl_%s_%s(VRT_CTX, const VCL_IP p)\n", anon ? "anon" : "named", acln); @@ -470,7 +470,7 @@ void vcc_ParseAcl(struct vcc *tl) { struct token *an; - int i; + struct symbol *sym; char acln[1024]; vcc_NextToken(tl); @@ -486,13 +486,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 893369e..464ad13 100644 --- a/lib/libvcc/vcc_compile.h +++ b/lib/libvcc/vcc_compile.h @@ -279,6 +279,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 294d12a..2e19cc6 100644 --- a/lib/libvcc/vcc_expr.c +++ b/lib/libvcc/vcc_expr.c @@ -502,10 +502,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, "&match_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); @@ -827,6 +845,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) @@ -849,6 +869,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 5a6c0fc..b4f6da1 100755 --- a/lib/libvcc/vmodtool.py +++ b/lib/libvcc/vmodtool.py @@ -46,6 +46,7 @@ from os.path import dirname, realpath, exists from pprint import pprint, pformat ctypes = { + 'ACL': "VCL_ACL", 'BACKEND': "VCL_BACKEND", 'BLOB': "VCL_BLOB", 'BOOL': "VCL_BOOL", diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc index 8b32e92..b16a43f 100644 --- a/lib/libvmod_debug/vmod.vcc +++ b/lib/libvmod_debug/vmod.vcc @@ -122,3 +122,7 @@ Return the dynamic backend. $Method VOID .refresh(STRING addr, STRING port) Dynamically refresh & (always!) replace the backend by a new one. + +$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 3dddbac..c7f920e 100644 --- a/lib/libvmod_debug/vmod_debug.c +++ b/lib/libvmod_debug/vmod_debug.c @@ -279,3 +279,13 @@ vmod_sleep(VRT_CTX, VCL_DURATION t) CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC); VTIM_sleep(t); } + +VCL_BOOL +vmod_match_acl(VRT_CTX, VCL_ACL acl, VCL_IP ip) { + + CHECK_OBJ_ORNULL(ctx, VRT_CTX_MAGIC); + AN(acl); + AN(ip); + + return acl(ctx, ip); +} -- 2.1.0
_______________________________________________ varnish-dev mailing list [email protected] https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev
