Opened 3 years ago

Closed 3 years ago

#2294 closed defect (invalid)

set $host url and auth_request failing on proxy_pass

Reported by: jack.pienso.com@… Owned by:
Priority: minor Milestone:
Component: documentation Version: 1.19.x
Keywords: Cc:
uname -a: Linux d12560761e0b 5.4.0-1057-gcp #61~18.04.1-Ubuntu SMP Thu Oct 28 04:16:28 UTC 2021 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.21.4
built by gcc 10.2.1 20210110 (Debian 10.2.1-6)
built with OpenSSL 1.1.1k 25 Mar 2021
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -ffile-prefix-map=/data/builder/debuild/nginx-1.21.4/debian/debuild-base/nginx-1.21.4=. -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'

Description (last modified by jack.pienso.com@…)

I'm trying to implement an auth_request call for an upstream host that is not guaranteed to be running.

My understanding is that, when calling proxy_pass, using set $foo some.service for an upstream host is the proper way to prevent nginx from throwing an error at boot, and properly resolving the IP address.

In isolation this pattern works fine:

location /happy/ {

set $a_endpoint http://my_service/;
proxy_pass $a_endpoint;

}

The following allows $a_endpoint to:

  1. not require the upstream host to be running when nginx starts
  2. dynamically update the IP address for the associated my_service.

I've tried to pair this with an auth_request and I see failing results

location /protected/ {

auth_request /oauth2/auth;
error_page 401 = /oauth2/sign_in;

set $a_endpoint http://my_service/;
proxy_pass $a_endpoint;

}

This first results is a 202 from the oauth API.

The second result is a 404 from the oauth API.

The second call is, in fact, being proxy_passed to the URL defined in auth_request? why...

I've verified that the second call is going to oauth instead of my_service in both debug nginx logs and wireshark.

Change History (4)

comment:1 by jack.pienso.com@…, 3 years ago

Description: modified (diff)

comment:2 by jack.pienso.com@…, 3 years ago

Description: modified (diff)

comment:3 by Maxim Dounin, 3 years ago

From what you describe it looks like you set $a_endpoint to a different value during auth subrequest handling. Variables use shared namespace for all subrequests (except for subrequest properties), and if you change $a_endpoint somewhere in auth subrequest handling, proxying will use this changed value.

Note that nginx configuration is declarative, not imperative, and set ... is actually takes place during processing of rewrite module directives. This happens just after selecting appropriate location and before access checks, notably auth_request.

If you only need variables in proxy_pass to force run-time name resolution, a more error-prone configuration would be to use a fixed empty variable, e.g.:

proxy_pass ${empty}http://example.com;

the variable itself can be provided by a map or geo at http level, e.g.:

geo $empty { default ""; }

(Note well that trailing slash in ​http://my_service/ is full URI when using variables, see proxy_pass documentation. Depending on how do you want it to work, you may want to remove it, as in the snippet above, or use something like $request_uri instead.)

comment:4 by Maxim Dounin, 3 years ago

Resolution: invalid
Status: newclosed

Feedback timeout. As explained above, the most likely reason is that the $a_endpoint variable is redefined during subrequest handling.

Note: See TracTickets for help on using tickets.