Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic authentication on routes #166

Closed
ygersie opened this issue Sep 27, 2016 · 18 comments
Closed

Basic authentication on routes #166

ygersie opened this issue Sep 27, 2016 · 18 comments
Milestone

Comments

@ygersie
Copy link

ygersie commented Sep 27, 2016

In Operations we often have to deal with Basic auth protected sites. The fabio-ui (#25) itself or announced routes for Nomad, Consul UI etc should be protected. The way we have to deal with that right now is setting up separate clusters consisting of:

  • Public fabio
  • Internal fabio (non protected)
  • Internal fabio (ldap protected behind a proxy)

It would be (more than) nice to be able to announce in the route itself that the resource should be protected with auth-type=ldap to perform Basic Auth. This saves us from a lot of configuration headaches and wasting resources on separating fabio instances and proxies and creating more VIPs to point to the correct clusters.

@tino
Copy link
Contributor

tino commented Jul 1, 2017

Or how about fetching the basic auth credentials from Vault? Seems like a sensible place to put 'em.

@csawyerYumaed
Copy link

or authenticate against vault auth directly. Then you can get LDAP or user/pass/etc auth "for free" as it were, without having to bring in all the LDAP libs directly into fabio. Bonus would be getting assigned vault policies to decide if they have access or not.

@magiconair
Copy link
Contributor

@csawyerYumaed That sounds like an interesting idea.

@magiconair magiconair added this to the Unplanned milestone Oct 10, 2017
@nmaludy
Copy link

nmaludy commented Mar 6, 2018

+1 for some sort of auth on routes, i really like the vault integration idea!

@aaronhurt
Copy link
Member

aaronhurt commented Mar 6, 2018

So out of curiosity how do you see this working?

vault that would take a method and raw kv arguments...

opts "auth=vault:method=method:arg1=value:arg2=value"

http basic auth...

opts "auth=basic:user1:pass1,basic:user1:pass2"

http digest auth...

opts "auth=digest:user1:realm1:hash1,digest:user2:realm2:hash2"

digest and basic...

opts "auth=digest:user1:realm1:hash1,basic:user1:pass1"

Seem reasonable? Just trying to think how this could be implemented. Would it try the definitions in order with fall-through? First match wins?

@aaronhurt
Copy link
Member

The reason I'm asking ... I could see this being an expansion to the ACL support that was recently added.

@nmaludy
Copy link

nmaludy commented Mar 6, 2018

@leprechau Yeah i think something along the lines of:

# auth : the name of the auth provider in the config (for things like secrets and htpasswd paths)
# type : what type of auth backend this is (vault, basic, digest)
# path : this is vault specific, maybe it makes sense to have this in the config?
# arg1=value1 : Backend specific key/value pairs to set in the auth request API call (for Vault) or maybe username=myuser for basic auth
auth=myvault:type=vault:method=ldap:path=ldap:arg1=value1:arg2=value2

Thinking the Vault token should probably be stored in the Fabio config instead of the route tags.

Also probably makes sense for basic auth to store the local path of the htpasswd file in the Fabio config?

Just brainstorming here.

@aaronhurt
Copy link
Member

I was thinking that auth=vault: would indicate it was from vault. The others would be handled strictly by fabio so we could have basic and digest handled by fabio for person(s) without vault running.

Maybe it could be: auth=vault:method:path:arg1=val1:arg2=val2:arg3=val3

Example for github to keep config short: auth=vault:github:auth/github/foo:token=xxxx

That would make the order of the options relevant but I think that would be okay as you would always need a method and path. The prefix vault:, basic:, digest: would always be stripped off and used to signal how to parse the rest of the string.

@magiconair
Copy link
Contributor

I'm not sure I like the fact that the password is stored in clear in the route tags. This is stored in consul and can be accessed via the api. Storing secrets feels like abusing the tags a bit too much. Also, this has to be deployed which means it has to be in some config file.

Secrets management is hard. That's why Vault exists.

I'm not saying that we shouldn't offer basic auth but keeping the passwords out of the route tags would be helpful IMO.

@nmaludy
Copy link

nmaludy commented Mar 6, 2018

I agree with @magiconair

Sort of what i envisioned was the following (taking after the existing proxy.cs pattern)

Config - /etc/fabio/fabio.conf

proxy.auth = auth=myvaultname;type=vault;method=ldap;path=myldappath;token=xyz123 \
            auth=mybasicname;type=basic;file=/etc/fabio/htpasswd

Service Definition - /etc/consul/myapp.json

{
  "services": [
    {
      "name": "myapp",
      "tags": ["myapp", "urlprefix-/myapp proto=https tlsskipverify=true auth=myvaultname"],
      "address": "",
      "port": 443,
      "enable_tag_override": false,
      "checks": [
        {
          "tcp": "127.0.0.1:443",
          "interval": "10s",
          "timeout": "1s"
        }
      ]
    }
  ]
} 

I haven't decided yet if the auth reference should be on the route tag, or in the config file. My only concern with having it on the route tag is: what if multiple instances of a service have conflicting auth references?

@magiconair
Copy link
Contributor

@nmaludy Then your deployment is broken just as if you'd have different services announcing the same route. I don't think there is much you can do about this. I might see a legit use case in migrating between auth sources as long as the underlying databases are in sync.

@nmaludy
Copy link

nmaludy commented Mar 6, 2018

@magiconair That's a very good point! Like you said the application deployment should be consistent via a Config Management tool or identical settings in your docker image(s). Also, your point about migrating to a different auth source is an interesting use case.

@aaronhurt
Copy link
Member

I agree secrets are hard, but I can’t think of a great way to offer basic auth without vault. You could reference an htpasswd file stored in consul? That’s better than password in the route.

@aaronhurt
Copy link
Member

I also think it would be nice to add auth without needing to restart fabio. If you only define the auth sources in the config you can’t dynamically add auth to a route without restarting fabio.

Allowing a file= or path= option on the route tag for basic and digest could work. Allowing the user to reference an on disk or consul stored htpasswd file.

@csawyerYumaed
Copy link

I'm ok with what @leprechau is saying:

Maybe it could be: auth=vault:method:path:arg1=val1:arg2=val2:arg3=val3
Example for github to keep config short: auth=vault:github:auth/github/foo:token=xxxx

But it would be super awesome if we could also say this vaultRole(which is returned as part of the token JSON after auth) can access or not.

auth=vault:method:path:roles=roleName1,roleName2:arg1=val1, etc.

So in this example you must have either roleName1 or roleName2 (as defined in vault) AND properly authenticate to get passed on.

@tholu
Copy link

tholu commented May 15, 2018

Basic support for a consul stored htpasswd/htdigest file would be very nice and a good simplification before LDAP/Vault support.

@magiconair
Copy link
Contributor

#573 implements some form of authentication so lets close this and have requests for other auth mechanisms in separate issues.

@magiconair magiconair modified the milestones: Unplanned, 1.5.11 Dec 10, 2018
@vjeantet
Copy link

Hello
Is this feature is working when proxy+sni is in use ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants