Cache results of auth_request module, keyed by username

10/19/2018

I am running the Kubernetes dashboard which, as one of its authentication methods, will allow you to pass the Authorization header with a bearer token in it. The token has to be a bearer token, i.e. Authorization: Bearer <token goes here>.

I am also running pam_hook as my authentication service. It uses HTTP basic auth to query PAM to get a user's groups, and it constructs a bearer token with that. I've modified it slightly to return the bearer token in the Authorization header after seeing this answer that tells me that you need to have it in the header for what I am trying to do: https://stackoverflow.com/a/31485557/691859

I have a fronting proxy (nginx) that uses the HTTP auth PAM module to secure the dashboard. Of course, I can have nginx forward the Authorization: Basic <basic auth goes here> header from this to pam_hook, and pam_hook can reply with the bearer token in an Authorization: Bearer <token goes here> header.

However, I'm having two problems:

  1. I am struggling to get the bearer token from pam_hook forwarded to the kubernetes dashboard; nginx is only forwarding the basic auth.
  2. Even if I was able to get it passed, I'm not sure how I can safely cache the responses. I need to cache each user's bearer token separately, otherwise, people will be able to act as each other. This answer alludes to that, but it doesn't tell you how to avoid the problem: https://stackoverflow.com/a/44232557/691859

So right now my config looks like this (I'm simplifying greatly here):

nginx.conf:

http {
  proxy_cache_path /tmp/cache levels=1:2 keys_zone=authentication:10m inactive=15m;
  proxy_cache_valid 200 15m;
  include /etc/nginx/conf.d/pam.conf;
  include /etc/nginx/conf.d/upstream.conf;
}

pam.conf:

auth_pam "Log in please";
auth_pam_service_name "nginx";

upstream.conf:

upstream backend {
  server localhost:9090
}

server {
  listen 443 default_server;

  location @upstream {
    proxy_pass https://backend;
    proxy_redirect off;
  }

  include /etc/nginx/conf.d/basic_auth_proxy.conf;

  location / {
    root /dev/null;
    try_files $uri @upstream;
    auth_request /basicauthproxy;
    auth_request_set $authorization_header $upstream_http_authorization;
    proxy_set_header Authorization $authorization_header;
  }
}

basic_auth_proxy.conf:

location /basicauthproxy {
  internal;

  proxy_pass              https://pamhook/token;
  proxy_cache             authentication;
  proxy_cache_key         $cookie_authentication;
  proxy_pass_request_body off;
  proxy_hide_header       Set-Cookie;
  proxy_ignore_headers    Set-Cookie;
  proxy_set_header        Cookie "";
  proxy_set_header        Host $host;
  proxy_set_header        Content-Length "";
  proxy_set_header        X-Original-URI $request_uri;
}

The behavior I get right now is that I get prompted for basic auth, pass my credentials, that succeeds, and then the dashboard gets the forwarded request... but the Authorization header contains the basic auth info from the proxy, not the bearer token. What am I missing to get this to work?

Edit: I upped the verbosity of pam_hook's logs. It's not getting any request from nginx. So that's probably the first problem to address, not that I understand why it's happening. I do know that I can curl pam_hook from the nginx container, so it's not a matter of a bad NetworkPolicy.

-- 2rs2ts
authentication
basic-authentication
kubernetes
nginx
pam

0 Answers