Hacker News new | ask | show | jobs
by zrail 1506 days ago
Neat to see this up here! When I saw xena's initial post about Grafana I saw an opportunity to make it work with an existing, well known, basically bullet proof proxy (nginx). Xena took my sketchy POC and made it great :)

One interesting enhancement, which is probably not within scope of this tool, would be a way to logically AND a bunch of these auth tools together. With that you could use this tool without changes to assert that someone is allowed on the tailnet then pass those results to a second process that checks what groups they belong to and authorizes them for the particular upstream being checked. One could accomplish that with one nginx proxy per application, of course, and lean into Tailscale's ACLs for authz.

2 comments

You might just want to integrate a policy rules engine like open policy agent: https://www.openpolicyagent.org/ It can act as a server which you bounce a subrequest against to get an authorization answer from a policy you defined ahead of time with a simple language.

And if you don't have time or want to do that, check out Pomerium it's basically a forward auth proxy with OPA policy engine integrated into it already: https://www.pomerium.com/

Yeah I've been thinking about that too. Something I've been wondering about is tying things to the ACL file through something like "capabilities"[1], but this would probably require a fair bit of per-service hacking. I think it'd be worth it, but it would be a lot of work. The main problem here is that Tailscale ACLs only really have "can connect to port" as the main capability they provide. I think I could end up telling the nginx-auth proxy if the person is a network admin or not (I'm not sure if that capability reliably shows up in whois responses, will need to check), that may be a starting point but it certainly won't scale.

[1]: https://github.com/tailscale/tailscale/issues/4217

That's an interesting issue, thanks for linking. I could see something like this working well:

  location /auth {
    ...
    proxy_set_header X-Required-Caps $required_caps;
    ...
  }

  location /grafana {   
    ...
    set $required_caps "grafana.com/read,grafana.com/write"
    auth_request_set $auth_caps $upstream_http_tailscale_caps;
    proxy_set_header X-Webauth-Caps $auth_caps;
    ...
  }
I.e. pass the caps through an nginx variable up to the `/auth` location, then out to `nginx-auth`, then nginx-auth passes all(?) of the user's caps to the upstream.