vmware-tanzu / kubeapps

A web-based UI for deploying and managing applications in Kubernetes clusters
Other
5k stars 707 forks source link

Oauth2 LDAP returns to login page #4699

Closed Ramshield closed 2 years ago

Ramshield commented 2 years ago

Describe the bug Hi,

I connected OpenLDAP to Dex to KubeApps. But when I login it returns me to the login screen of Kubeapps. I get a authorization token and the logs says the login attempt is successful.

A GIF will be added shortly.

To Reproduce

values_dex.yaml:

ingress:
  enabled: true

  className: ""

  annotations: {}

  hosts:
    - host: dex.test.local
      paths:
        - path: /
          pathType: ImplementationSpecific

  tls:
    - secretName: dex.test.local.certs
      hosts:
        - dex.test.local

https:
  enabled: false

config:
  issuer: https://dex.test.local/

  storage:
    type: memory

  enablePasswordDB: true

  connectors:
    - type: ldap
      name: OpenLDAP
      id: ldap
      config:
        host: openldap.openldap.svc.cluster.local:389
        insecureNoSSL: true

        bindDN: cn=admin,dc=test,dc=local
        bindPW: Not@SecurePassw0rd

        usernamePrompt: Email Address

        userSearch:
          baseDN: ou=People,dc=test,dc=local
          filter: "(objectClass=person)"
          username: mail
          idAttr: DN
          emailAttr: mail
          nameAttr: cn

        groupSearch:
          baseDN: ou=Groups,dc=test,dc=local
          filter: "(objectClass=groupOfNames)"

          userMatchers:
            - userAttr: DN
              groupAttr: member

          nameAttr: cn

  staticClients:
  - id: example-app
    redirectURIs:
      - http://kubeapps.test.local/oauth2/callback
    name: 'Example App'
    secret: ZXhhbXBsZS1hcHAtc2VjcmV0

web:
  http: 0.0.0.0:5556

values_kubeapps.yaml:

authProxy:
  enabled: true
  provider: "oidc"
  clientID: "example-app"
  clientSecret: "ZXhhbXBsZS1hcHAtc2VjcmV0"
  cookieSecret: "bm90LWdvb2Qtc2VjcmV0Cg=="
  cookieRefresh: 2m
  scope: "openid email groups"
  emailDomain: "*"
  extraFlags:
    - --ssl-insecure-skip-verify
    - --cookie-secure=false
    - --oidc-issuer-url=https://dex.test.local/
    - --set-authorization-header=true
    - --pass-authorization-header=true

ingress:
  enabled: true
  tls: false
  selfSigned: false
  hostname: kubeapps.test.local

  annotations:
    nginx.ingress.kubernetes.io/proxy-buffer-size: "64k"
    nginx.ingress.kubernetes.io/proxy-buffers-number: "8"

It's a normal OpenLDAP, and I tested it with the example app from Dex and authentication works.

Dex logs:

time="2022-05-12T13:13:06Z" level=info msg="Dex Version: v2.31.1-dirty, Go Version: go1.17.8, Go OS/ARCH: linux amd64"
time="2022-05-12T13:13:06Z" level=info msg="config issuer: https://dex.test.local/"
time="2022-05-12T13:13:06Z" level=info msg="config storage: memory"
time="2022-05-12T13:13:06Z" level=info msg="config static client: Example App"
time="2022-05-12T13:13:06Z" level=info msg="config connector: ldap"
time="2022-05-12T13:13:06Z" level=info msg="config connector: local passwords enabled"
time="2022-05-12T13:13:06Z" level=info msg="config refresh tokens rotation enabled: true"
time="2022-05-12T13:13:06Z" level=info msg="keys expired, rotating"
time="2022-05-12T13:13:06Z" level=info msg="keys rotated, next rotation: 2022-05-12 19:13:06.950433627 +0000 UTC"
time="2022-05-12T13:13:06Z" level=info msg="listening (telemetry) on 0.0.0.0:5558"
time="2022-05-12T13:13:06Z" level=info msg="listening (http) on 0.0.0.0:5556"
time="2022-05-12T13:14:33Z" level=info msg="performing ldap search ou=People,dc=test,dc=local sub (&(objectClass=person)(mail=janedoe@example.com))"
time="2022-05-12T13:14:33Z" level=info msg="username \"janedoe@example.com\" mapped to entry cn=jane,ou=People,dc=test,dc=local"
time="2022-05-12T13:14:33Z" level=info msg="performing ldap search ou=Groups,dc=test,dc=local sub (&(objectClass=groupOfNames)(member=cn=jane,ou=People,dc=test,dc=local))"
time="2022-05-12T13:14:33Z" level=info msg="login successful: connector \"ldap\", username=\"jane\", preferred_username=\"\", email=\"janedoe@example.com\", groups=[\"admins\" \"developers\"]"

Kubeapps auth-proxy logs:

10.244.1.32:49688 - 634703ffb43519fd2be1c6128ea52b06 - janedoe@example.com [2022/05/12 13:14:35] [AuthSuccess] Authenticated via OAuth2: Session{email:janedoe@example.com user:CiJjbj1qYW5lLG91PVBlb3BsZSxkYz10ZXN0LGRjPWxvY2FsEgRsZGFw PreferredUsername: token:true id_token:true created:2022-05-12 13:14:35.38314449 +0000 UTC m=+44.319959528 expires:2022-05-13 13:14:34.379558547 +0000 UTC m=+86443.316373583 groups:[admins developers]}
10.244.1.32:49688 - 634703ffb43519fd2be1c6128ea52b06 - - [2022/05/12 13:14:35] kubeapps.test.local GET - "/oauth2/callback?code=by56hcs7p5pfgjpk76ht44ciq&state=1xATpdn42fnrkOa8Qt-WURadthRjfxSdFWVosqFFx10%3A%2F" HTTP/1.1 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36" 302 24 0.010
10.244.1.32:49688 - 8b413075a16867ad4663b53084b304ae - janedoe@example.com [2022/05/12 13:14:35] kubeapps.test.local GET / "/static/css/2.74be0ed9.chunk.css" HTTP/1.1 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36" 200 211499 0.012
10.244.1.32:50200 - 5fa313335b4f1f785a41f31314b06b47 - janedoe@example.com [2022/05/12 13:14:35] kubeapps.test.local GET / "/static/css/main.2ef2650c.chunk.css" HTTP/1.1 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36" 200 9246 0.002
10.244.1.32:49886 - 7c42d2e0324e34fa2523031ca74a329e - janedoe@example.com [2022/05/12 13:14:35] kubeapps.test.local GET / "/static/js/main.53a40e0c.chunk.js" HTTP/1.1 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36" 200 99260 0.007
10.244.1.32:50200 - 68ca15fb251434441b4930a61509f188 - janedoe@example.com [2022/05/12 13:14:37] kubeapps.test.local GET / "/config.json" HTTP/1.1 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36" 200 446 0.001
10.244.1.32:50200 - 818385bdb4832c86df5c6ef364b67645 - janedoe@example.com [2022/05/12 13:14:37] kubeapps.test.local GET / "/clr-ui-dark.min.css" HTTP/1.1 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36" 200 142773 0.008
10.244.1.32:49886 - ab891f80e734ae1e05d12fb5c28ca86c - janedoe@example.com [2022/05/12 13:14:37] kubeapps.test.local GET / "/favicon-32x32.png" HTTP/1.1 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36" 200 1836 0.001
10.244.1.32:49688 - f77a51541dae0a1bbb26d7a3add556db - janedoe@example.com [2022/05/12 13:14:37] kubeapps.test.local POST / "/apis/kubeappsapis.plugins.resources.v1alpha1.ResourcesService/CheckNamespaceExists" HTTP/1.1 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36" 200 0 0.08

The only error I get from kubeapps-internal-kubeappsapis-595fc49846-6rsbv which doesn't say anything to me:

I0512 13:14:37.679493       1 namespaces.go:24] +resources CheckNamespaceExists (cluster: "default", namespace="default")
I0512 13:14:37.744908       1 server.go:59] Unauthenticated 69.779311ms /kubeappsapis.plugins.resources.v1alpha1.ResourcesService/CheckNamespaceExists

Expected behavior Be able to login.

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information): Windows/MacOS, Safari, Chrome

$ helm list -n kubeapps
NAME        NAMESPACE   REVISION    UPDATED                                 STATUS      CHART           APP VERSION
kubeapps    kubeapps    7           2022-05-10 09:25:00.660446995 +0000 UTC deployed    kubeapps-8.0.16 2.4.5
antgamdia commented 2 years ago

Thanks for the report! We will try to look into and reproduce it; adding it to our next iteration discussion.

Ramshield commented 2 years ago

Thanks @antgamdia. We tried this in 3 stand-alone environments but resulting in the same thing.

absoludity commented 2 years ago

@Ramshield I've just checked my local dev environment, which sets up ldap with dex, and it worked fine. You can try it out in a kind cluster (make cluster-kind && make deploy-dev, the development user/password is kubeapps-operator-ldap@example.org/password as per the ldap config, see the development Makefile for more detail about what it sets up to compare to your own).

Note: for the situation you describe, where you see logs that the authentication was successful, but Kubeapps redirects you to the login page, this is nearly always because you successfully authenticated, but the token passed back to Kubeapps doesn't have access to view the cluster. You can follow the instructions for debugging OIDC issues to find the actual token and test the token itself.

Let us know if that helps.

Ramshield commented 2 years ago

Thanks @absoludity the kind environment works for us. I applied the same [RBAC rules](https://github.com/vmware-tanzu/kubeapps/blob/main/site/content/docs/latest/reference/manifests/kubeapps-local-dev-users-rbac.yaml but still getting the redirect.

After applying the --oidc-x settings to the manifest of kubeapi I am getting a bit better result. However for our production environment we use Rancher. I don't want/can't set oidc for all the downstream clusters of rancher, and want to apply it to 1 specific cluster only. However Rancher doesn't work with manifests and Google isn't really of much help. Any advice you can give here, how to get this working in a Rancher environment?

absoludity commented 2 years ago

OK, so to be clear, what I've understood from your last comment is that the issue is that your cluster is not configured to accept OIDC tokens for authentication, I think?

Sorry, I don't have any Rancher specific knowledge I can give here, but what I can recommend is that you follow the debugging instructions that I've linked to above, so that you can see the actual token being returned and then verify (via curl or otherwise) whether that token allows access to the cluster or not. I'm guessing it doesn't since you cluster isn't configured for oidc.

Once you have the token, you can try a few things (without involving Kubeapps) to see if you can somehow query the API server with the token received. For example, checking the rancher docs, I see the APIserver is most likely configured with a web-hook auth pointing at the rancher kube-api-auth service. I've not checked to see what that expects, but it could that the Rancher web hook i expecting the access_token rather than the oidc id_token.

We had a similar situation in the past with cloud providers in the past (eg. GKE, though they now also support oidc), where they would only accept the separate access_token. There's a chart option for Kubeapps which will use the access token instead, you can read about it at Example 3 at how to setup oidc for oauth2-proxy, in particular, note the --set frontend.proxypassAccessTokenAsBearer=true being passed there. Again, I would not just jump in and test this with Kubeapps (or if you do, don't be disappointed if it doesn't work), but instead, find out how you can get the access token back during the auth exchange and test it with curl. If you then find it works, then we should be able to get it to work with Kubeapps.

If that doesn't work, another option might be to install https://pinniped.dev/ on this cluster, pinniped makes cluster auth safe and easy, and Kubeapps supports oidc via pinniped too (more info in our docs).

HTH!

Ramshield commented 2 years ago

For anyone who's wondering, since we use Rancher we figured out you can login with your cluster token. This is a perfect solution without using 3rd party software and works with LDAP integration.