mintel / dex-k8s-authenticator

A Kubernetes Dex Client Authenticator
MIT License
374 stars 146 forks source link

No page styling when running authenticator under a path #40

Closed eroji closed 6 years ago

eroji commented 6 years ago

I am trying to deploy k8s-authenticator under /login path while I managed to get Dex working under /dex. It seems like a good way to make the URL clean and neat. However, when the pod spins up with Nginx ingress rule, the authenticator page loads with no styling at all. My guess is, it is not able to see that the context path should now be /login. Is there a way to fix this?

global:
  deployEnv: test

replicaCount: 1

image:
  repository: mintel/dex-k8s-authenticator
  tag: latest
  pullPolicy: Always

dexK8sAuthenticator:
  port: 5555
  debug: false
  logoUrl: https://cluster.domain.com/logo/small.png
  clusters:
  - name: test-cluster
    short_description: "Test Cluster"
    description: "Test Kubernetes Cluster"
    client_secret: pUBnBOY80SnXgjibTYM9ZWNzY2xreNGQok
    issuer: https://cluster.domain.com/dex
    k8s_master_uri: https://cluster.docmagic.com
    client_id: test-cluster
    redirect_uri: https://cluster.domain.com/login/callback
    k8s_ca_uri: https://cluster.domain.com/k8s/atlas-ca.crt

service:
  type: ClusterIP
  port: 5555

ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: nginx
  path: /login
  hosts:
    - cluster.domain.com
  tls:
    - secretName: domain-tls-cert
      hosts:
        - cluster.domain.com

resources: {}

nodeSelector: {}

tolerations: []

affinity: {}
nabadger commented 6 years ago

@eroji I'll take a look.

There is a problem with the re-write of static html and I can re-reproduce it now.

There is however another issue here (I think) in that you're using /login - the dex-k8s-auth app. generates this URI internally, so you will probably end up with /login/login if you go down this route.

If you avoid setting your ingress rule to /login and just have / - this setup works (it did for me at least).

I don't think this is a nice solution though, as it basically means anything under /dex is served by Dex, and anything under / is served by dex-k8s-auth.

Once I figure out how to fix the static-uri rewriting, you will probably still need to deal with the fact that dex-k8s-auth creates a login URI internally - maybe you can have something like /dex and /dexk8sauth (which then gives you /dexk8sauth/login

eroji commented 6 years ago

It doesn't necessary have to be '/login'. That was just a path I picked arbitrarily. My goal is to have / served by a static page, most likely deployed via a webserver pod, which will have landing page for users with links to the dashboard, to k8s-authenticator and potentially other cluster related assets, also some path for serving the apiserver CA cert. I think it would be the cleanest solution instead of having a half a dozen DNS records.

nabadger commented 6 years ago

I was thinking this could maybe be achieved with some of Ingress options - but that depends on the Ingress impl. used (for example nginx sub_filter might achieve this).

For now I'll take a look and add something like a webPathPrefix that can be done as a config option - that way it can all be handled by the dex-k8s-auth application

eroji commented 6 years ago

Just a quick node, I had to modify Dex deployment config for the health check URL to be /dex/healthz instead. The standard /healthz that came with the Helm chart was causing the liveness monitor to kill the pod repeatedly. I tried playing with ingress annotation to possibly get around this without avail so that was what I had to resort to.

nabadger commented 6 years ago

Ok, I'll take that into account and add an optional override for health-check urls.

Should be able to get to this at the end of the week 👍

eroji commented 6 years ago

Awesome! Thank you!

nabadger commented 6 years ago

@eroji There's a branch you can look at above - I've tested it in minikube using the Helm charts.

If you don't want to build the image, there's one that I've uploaded here: nabadger/dex-k8s-authenticator:feat-path-prefix

You should just need to set the web_path_prefix in the dex-k8s-auth. helm chart values, and point also use the above image (or build your own from this branch)

Make sure the prefix has a trailing slash, like /login/

You also need to update the associated callback uri in the dex-config to use the same prefix.

If you don't set the web_path_prefix it maintains the default functionality.

Let me know if this PR works for you :)

Cheers

eroji commented 6 years ago

Thank you. However, I think there is something funky going on with the liveness/readiness monitors. It's not detecting the pod in "ready" state.

This is the Helm chart I am using for deploying.

global:
  deployEnv: cluster

replicaCount: 1

image:
  repository: nabadger/dex-k8s-authenticator
  tag: feat-path-prefix
  pullPolicy: Always

dexK8sAuthenticator:
  port: 5555
  debug: false
  logoUrl: https://www.domain.com/logo.png
  clusters:
  - name: cluster
    short_description: "My Cluster"
    description: "My Kubernetes Cluster"
    client_secret: 12345ABCDE
    issuer: https://k8s.domain.com/dex
    k8s_master_uri: https://k8s-api.domain.com
    client_id: cluster
    redirect_uri: https://k8s.domain.com/auth/login/callback
    web_path_prefix: /auth/
    k8s_ca_uri: https://k8s.domain.com/ca/cluster-ca.crt

service:
  type: ClusterIP
  port: 5555

ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: nginx
  path: /auth
  hosts:
    - k8s.domain.com
  tls:
    - secretName: domain-tls-cert
      hosts:
        - k8s.domain.com

resources: {}

nodeSelector: {}

tolerations: []

affinity: {}
nabadger commented 6 years ago

I'll have a look - when I worked on it earlier my ingress path would have been /

nabadger commented 6 years ago

@eroji This still works on my setup (now with the same ingress path).

Do you get a chance to see any logs (kubectl logs) from the dex-k8s-auth pod?

If not, what does kubectl describe on the pod show - the health checks should just be referencing /auth/

Also check the configmap for dex-k8s-auth - it should have the web_path_prefix set in the config (generated by the helm template).

Most of the time when dex-k8s-auth fails to start, it's because it can't validate the issuer.

If you fire up a busybox pod, then try and check the state of dex from within the cluster with: wget https://k8s.domain.com/dex/.well-known/openid-configuration

May not work due to SSL (a cURL pod would be better)

nabadger commented 6 years ago

@eroji ah - your helm config is wrong, as web_path_prefix works at the top level such as

dexK8sAuthenticator:
  port: 5555
  debug: false
  #logoUrl: http://<path-to-your-logo.png>
  web_path_prefix: /auth/
  clusters:
  - name: my-cluster
    short_escription: "minikube"
    description: "minikube"
    ...
eroji commented 6 years ago

Looks like I still had to override the liveness/readiness path to /auth for it to be available. However, it's still showing the page without styling. Do I need any particular nginx ingress annotation?

nabadger commented 6 years ago

You don't need anything on the ingress, nor do you need to override the liveness/readiness path's as that's taken from web_path_prefix and the helm template configures that for you.

Can you confirm you are using the helm charts from the Feat path prefix branch?

It should have the following in ./charts/dex-k8s-authenticator/templates/deployment.yaml

   livenessProbe:
          httpGet:
            path: {{ .Values.dexK8sAuthenticator.web_path_prefix }}
            port: http
        readinessProbe:
          httpGet:
            path: {{ .Values.dexK8sAuthenticator.web_path_prefix }}
            port: http

Here are the full helm values that I use for dex and dex-k8s-auth:

# Default values for dex
global:
  deployEnv: dev

replicaCount: 1

image:
  repository: quay.io/coreos/dex
  tag: v2.9.0
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 5556

ingress:
  enabled: true
  annotations: {}
  path: /
  hosts:
    - dex.minikube.test
  tls: []

rbac:
  create: true

serviceAccount:
  create: true
  name:

resources: {}
nodeSelector: {}
tolerations: []
affinity: {}

# Configuration file for Dex
# Certainly secret fields can use environment variables
#
config: |-
  issuer: http://dex.minikube.test

  storage:
    type: sqlite3
    config:
      file: dex.db

  web:
    http: 0.0.0.0:5556

  frontend:
    theme: "coreos"
    issuer: "Example Co"
    issuerUrl: "https://example.com"
    logoUrl: https://example.com/images/logo-250x25.png

  expiry:
    signingKeys: "6h"
    idTokens: "24h"

  logger:
    level: debug
    format: json

  oauth2:
    responseTypes: ["code", "token", "id_token"]
    skipApprovalScreen: true

  staticClients:
  - id: my-cluster
    name: "my-cluster"
    secret: "pUBnBOY80SnXgjibTYM9ZWNzY2xreNGQok"
    redirectURIs:
    - http://auth.minikube.test/auth/callback/my-cluster

  enablePasswordDB: True
  staticPasswords:
  - email: "admin@example.com"
    # bcrypt hash of the string "password"
    hash: "$2a$10$2b2cU8CPhOTaGrs1HRQuAueS7JTT5ZHsHSzYiFPm1leZck7Mc8T4W"
    username: "admin"
    userID: "08a8684b-db88-4b73-90a9-3cd1661f5466"
# Helm example for dex-k8s-authenticator.
global:
  deployEnv: dev

replicaCount: 1

image:
  repository: nabadger/dex-k8s-authenticator
  tag: feat-path-prefix
  pullPolicy: Always

dexK8sAuthenticator:
  port: 5555
  debug: false
  web_path_prefix: /auth/
  clusters:
  - name: my-cluster
    short_description: "minikube"
    description: "minikube"
    client_secret: pUBnBOY80SnXgjibTYM9ZWNzY2xreNGQok
    issuer: http://dex.minikube.test
    k8s_master_uri: http://my-cluster.example.com
    client_id: my-cluster
    redirect_uri: http://auth.minikube.test/auth/callback/my-cluster
    k8s_ca_uri: http://ca.example.com/

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: true
  path: /auth
  hosts:
    - auth.minikube.test

resources:
  limits:
    cpu: 100m
    memory: 100Mi
  requests:
    cpu: 50m
    memory: 50Mi

certs:
  create: false

nodeSelector: {}
tolerations: []
affinity: {}
eroji commented 6 years ago

Ok, that was my problem. I needed to pull down the branch. It is working now. Thank you very much and my apologies for the confusion!

nabadger commented 6 years ago

Ok sure - I'll merge this to master and add documentation and create a new release this week.

eroji commented 6 years ago

I noticed that in your example, Dex is using it's own hostname and /. Since I was using /dex for the same hostname as authenticator, I did need to override the /healthz check like I did before.