So recently I learned that OpenResty's access_by_lua_block and the satisfy any directive don't play nice together. To be honest I didn't have a very compelling reason to use an access_by_lua_block to begin with. Ideally I would have used a set_by_lua_block, but subrequests using ngx.location.capture are disabled by it since it is a blocking function.
Still I felt a bit conflicted about whether I should be using access_by_lua or rewrite_by_lua, since technically all I really wanted to do was set a variable (to print in the access logs) and am neither authenticating or rewriting. Using either one seems like a hacky workaround.
As it turns out, rewrite_by_lua is the much safer option if you use any authentication directives. Take for example this situation:
- I need to set a variable using an external microservice and decide to do so with ngx.location.capture
- It's a private API with complex authentication rules (ie a combination of IP blocking and basic auth)
So something like this:
server { set $my_special_variable "0"; # fallback value if no response from microservice access_by_lua_block { local res = ngx.location.capture("/microservice") if res then ngx.var.my_special_variable = res.body end } location ~ /private/api/endpoint { satisfy any; allow [some ip address]; deny all; auth basic "unauthorized"; auth_basic_user_file /etc/nginx/.htpasswd; proxy_pass http://my_backend_server; } } .
Unfortunately the access_by_lua_block counts as a satisfied condition for the satisfy any; directive and suddenly my API is opened up to the world: neither the correct IP or basic auth is required to access it anymore. Everyone can access it. Huge security risk to say the least.
So it still feels bit hacky since the subrequest to the microservice isn't involved doing any uri rewriting to speak of, but rewrite_by_lua_block is definitely the better option in this situation. Glad I caught this technicality early on.