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

Secure access to in-cluster headlamp with a reverse proxy #2207

Open
mlbiam opened this issue Jul 26, 2024 · 21 comments
Open

Secure access to in-cluster headlamp with a reverse proxy #2207

mlbiam opened this issue Jul 26, 2024 · 21 comments
Assignees
Labels
backend Issues related to the backend blocker Completely prevents the user from using the software. oidc Issue related to OIDC security
Milestone

Comments

@mlbiam
Copy link

mlbiam commented Jul 26, 2024

I'd like to integrate HeadLamp into OpenUnison (https://openunison.github.io), but I'm running into a few issues:

OIDC doesn't support self signed CA - Going through the instructions for OIDC ignores trusting a certificate. This makes OIDC mostly useless for identity prociders that aren't publicly hosted, like OpenUnison, in an enterprise environment which usually has its own internal CA.

OIDC uses a client secret - Kubernetes will require the audience to be the same for kubectl and your cluster, but that means that using client secret means all kubectl users also need a client secret (this is technically not true with 1.30+, but additional token types will take quite some time to be available, if ever, to commercial distributions and managed clusters). Distributing a client secret is an anti pattern for kubectl use because it's now a shared password and will need to be treated as such by more enterprise security policies.

OIDC doesn't support impersonation - There's no way to integrate incluster headlamp with a managed cluster.

For these reasons, I'd like to propose a reverse proxy approach for in-cluster, similar to how the Kubernetes Dashboard, Kiali (Istio Dashboard), and the Tekton Dashboard all work. A revesrse proxy architecture allows a revese proxy, such as OpenUnison or OAuth2 proxy, to inject a token, and potentially impersonation headers, into each request. It then becomes the responsibility of the reverse proxy to keep the authentication token (and impersonation headers) up to date.

I'm happy to contribute code to make this work, but I want to make sure the project is willing to integrate this feature before I dive into doing the work.

@joaquimrocha
Copy link
Collaborator

Hi @mlbiam , while I'd like to understand what this implies for the project (what dependencies it brings, what we have to maintain, does UX change at all?), in principle we agree with having ways of deploying Headlamp that improve security or validate different use-cases. So I am happy to work with you to land this.

@joaquimrocha joaquimrocha added this to the v0.26.0 milestone Jul 26, 2024
@joaquimrocha joaquimrocha added backend Issues related to the backend security oidc Issue related to OIDC labels Jul 26, 2024
@umarhussain15
Copy link

Hi,
Thanks for opening the discussion on additional uses case of authentication.
I think impersonation is a good idea as it can decouple the OIDC used by cluster and OIDC used by headlamp. In my case, the cluster does not have the OIDC auth enabled by the provider, so the current setup of headlamp with OIDC will not work in this environment.

We can use the example of weavworks GitOps dashboard, where the OIDC authenticates the user to the application, the dashboard application then sends the user impersonation token in each request to the API server (application needs a service account with impersonation of user and group). This will also translate nicely to already configured RBAC in the cluster, e.g. if cluster admins have already configured the same groups as returned in user's token

References:

@joaquimrocha joaquimrocha modified the milestones: v0.26.0, v0.27.0 Nov 16, 2024
@mlbiam
Copy link
Author

mlbiam commented Dec 10, 2024

@umarhussain15 this is how it works with the current Kubernetes Dashboard too

@joaquimrocha
Copy link
Collaborator

Thanks for the pointers. We definitely want to support this as an option.
The first link shared by @umarhussain15 is broken now. Do you have alternatives we can look into to get a more complete picture?

@umarhussain15
Copy link

Oh, looks like the website is taken down now as well, as weaveworks shutdown.
I found the documentation in their Git repo here: https://github.com/weaveworks/weave-gitops/blob/main/website/docs/enterprise/getting-started/install-enterprise.mdx#set-up-authentication-and-rbac

@mlbiam
Copy link
Author

mlbiam commented Dec 11, 2024

for reference, here's the PR that enabled this in the Kubernetes Dashboard - https://github.com/kubernetes/dashboard/pull/4082/commits

@audunsolemdal
Copy link

As a cluster admin trying to migrate from Weave GitOps to Headlamp in-cluster I am impressed by the product. However the lack of impersonation support through OIDC login is a unfortunately a blocker for adoption by developer teams in my org...

@joaquimrocha joaquimrocha modified the milestones: v0.27.0, v0.28.0 Dec 13, 2024
@joaquimrocha joaquimrocha modified the milestones: v0.28.0, v0.29.0 Jan 20, 2025
@illume illume added the blocker Completely prevents the user from using the software. label Jan 21, 2025
@joaquimrocha joaquimrocha assigned yolossn and unassigned yolossn Jan 28, 2025
@umarhussain15
Copy link

Linking the new PR which will enable it 🎉

#2814

@yolossn
Copy link
Contributor

yolossn commented Feb 10, 2025

@mlbiam

OIDC uses a client secret - Kubernetes will require the audience to be the same for kubectl and your cluster, but that means that using client secret means all kubectl users also need a client secret (this is technically not true with 1.30+, but additional token types will take quite some time to be available, if ever, to commercial distributions and managed clusters). Distributing a client secret is an anti pattern for kubectl use because it's now a shared password and will need to be treated as such by more enterprise security policies.

can you explain this please? AFAIU the client secret will be set by the admin in in-cluster deployment only, why will there be a need to distribute client secret?

@yolossn
Copy link
Contributor

yolossn commented Feb 10, 2025

@mlbiam

I took a look into the OIDC impersonation implementation in Kubernetes Dashboard. From my understanding, adding OIDC Impersonation support in Headlamp is not so straight forward as Kubernetes Dashboard. In Kubernetes Dashboard the client is created for every request with the impersonation details, where as in headlamp a proxy to the Kubernetes api-server is established in the beginning and requests are proxied with the authentication headers from frontend.

Right now we have one proxy per cluster, if we want to support impersonation (which involves adding impersonation details to clientcmd/api.AuthInfo) we will have to create one proxy per user per cluster.

@knrt10 @illume WDYT?

handleImpersonation is used in Client and the client is initialised in all the requests 1 2...

@mlbiam
Copy link
Author

mlbiam commented Feb 10, 2025

can you explain this please? AFAIU the client secret will be set by the admin in in-cluster deployment only, why will there be a need to distribute client secret?

If you require a client secret for a client in your identity provider, it must always be used. In this case, that means both server side applications like headlamp and cli applications like kubectl. This is why Kuberentes made client secrets optional, distributing the client secret to anyone using kubectl is impractical (and gets treated as a password by most enterprise compliance requirements causing all kinds of headaches). Since Kubernetes can only support a single issuer (this changes in 1.30 but is still in beta and is not available for commercial distributions yet), it means that your identity provider can't be split up between a CLI idp and a server side idp. So that means to use both headlamp in-cluster and kubectl you'd need to distribute the client secret to anyone using kubectl

@mlbiam
Copy link
Author

mlbiam commented Feb 10, 2025

From my understanding, adding OIDC Impersonation support in Headlamp is not so straight forward as Kubernetes Dashboard. In Kubernetes Dashboard the client is created for every request with the impersonation details,

Correct

where as in headlamp a proxy to the Kubernetes api-server is established in the beginning and requests are proxied with the authentication headers from frontend.

you support oidc now, don't you have the same problem? If you have two users signed in via OIDC, how do you keep their sessions separate? If you're not maintaining user specific connections, that means a user with admin access to a specific namespace could use the credentials of a user with cluster-admin access??? Even two users with the same permission levels would have an issue because the audit logs could show either one as the user that executed an action. That sounds like a significant security issue.

@yolossn
Copy link
Contributor

yolossn commented Feb 10, 2025

you support oidc now, don't you have the same problem? If you have two users signed in via OIDC, how do you keep their sessions separate?

For a cluster configured with OIDC the proxy that is created is an unauthenticated proxy that can be used by anyone with proper auth headers.

Once the user completes the OIDC flow the code that is returned in the callback is exchanged for a token and is sent to the frontend, the frontend sends the token in Authorization header which is forwaded to the proxy. So I don't see permission mismatch issues.

@yolossn
Copy link
Contributor

yolossn commented Feb 10, 2025

If you require a client secret for a client in your identity provider, it must always be used. In this case, that means both server side applications like headlamp and cli applications like kubectl. This is why Kuberentes made client secrets optional, distributing the client secret to anyone using kubectl is impractical (and gets treated as a password by most enterprise compliance requirements causing all kinds of headaches). Since Kubernetes can only support a single issuer (this changes in 1.30 but is still in beta and is not available for commercial distributions yet), it means that your identity provider can't be split up between a CLI idp and a server side idp. So that means to use both headlamp in-cluster and kubectl you'd need to distribute the client secret to anyone using kubectl

AFAIU A different client can be created in the IDP for headlamp right? As long as the token that is provided by the client with secret has the claims that are accepted by the kubernetes api-server it should work without any hassle.

@yolossn
Copy link
Contributor

yolossn commented Feb 10, 2025

I just came across user-impersonation, as long as the reverse proxy adds the proper impersonation headers to the proxied requests, headlamp will forward it to the api-server and it should work as expected. Can you share the logs or any other info that can help me understand the errors that you faced with impersonation?

@mlbiam
Copy link
Author

mlbiam commented Feb 10, 2025

AFAIU A different client can be created in the IDP for headlamp right? As long as the token that is provided by the client with secret has the claims that are accepted by the kubernetes api-server it should work without any hassle.

no, kubernetes also gets configured with an expected client via --oidc-client-id. so you can't use a different client for headlamp as kubectl.

@mlbiam
Copy link
Author

mlbiam commented Feb 10, 2025

Once the user completes the OIDC flow the code that is returned in the callback is exchanged for a token and is sent to the frontend, the frontend sends the token in Authorization header which is forwaded to the proxy. So I don't see permission mismatch issues.

tbc, you're saying that every request to the API server from headlamp has a unique userInfo?

I just came across user-impersonation, as long as the reverse proxy adds the proper impersonation headers to the proxied requests, headlamp will forward it to the api-server and it should work as expected. Can you share the logs or any other info that can help me understand the errors that you faced with impersonation?

i havne't tested out the PR yet, but based on your description is should be OK. i'm more concerned about your original statement that the proxy is tied to a cluster, not a user. For impersonation to work correctly you should be passing the token and the impersonation headers on every request to the API server. I've not reviewed the PR yet to confirm that's what's happening.

@yolossn
Copy link
Contributor

yolossn commented Feb 14, 2025

tbc, you're saying that every request to the API server from headlamp has a unique userInfo?

Yes, the token is stored in the frontend and sent with every request to the cluster.

i'm more concerned about your original statement that the proxy is tied to a cluster, not a user.

The proxy created by the backend is cluster-specific. The user information is sent by the frontend, so we only need a single proxy per cluster.

For impersonation to work correctly you should be passing the token and the impersonation headers on every request to the API server. I've not reviewed the PR yet to confirm that's what's happening.

I'm setting up Headlamp with OpenUnison to verify if this works as expected. I'll update here once I have tested it.

@mlbiam
Copy link
Author

mlbiam commented Feb 14, 2025

I'm setting up Headlamp with OpenUnison to verify if this works as expected. I'll update here once I have tested it.

@yolossn feel free to ping me in the headlamp slack

@joaquimrocha joaquimrocha modified the milestones: v0.29.0, v0.30.0 Feb 18, 2025
@yolossn
Copy link
Contributor

yolossn commented Feb 23, 2025

Quick Update, I was able to test if the Impersonation headers are working without installing openunison by a workaround. I used AKS with Entra ID auth setup for this.

  1. Install headlamp in a cluster which has OIDC authentication enabled

helm install headlamp headlamp/headlamp \
--namespace openunison
--create-namespace
--set config.baseURL="/headlamp"

  1. Create required role and rolebindings.
kubectl apply -f config.yaml

config.yaml

# 1. Role for the admin user who will perform impersonation
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: impersonator
rules:
- apiGroups: [""]
  resources: ["users", "groups"]
  verbs: ["impersonate"]
---
# 2. Binding for the admin user
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: impersonator-binding
subjects:
- kind: User
  name: admin-user  # The user who will be doing the impersonation
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: impersonator
  apiGroup: rbac.authorization.k8s.io
---
# 3. Role for test-user2
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: test-user2-role
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
---
# 4. Binding for test-user2
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: test-user2-binding
  namespace: default
subjects:
- kind: User
  name: test-user2  
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: test-user2-role
  apiGroup: rbac.authorization.k8s.io
  1. Portforward to headlamp using kubectl

kubectl port-forward svc/headlamp 4000:80 -n openunison

Image
  1. Fetch headlamp config to check if headlamp is running
curl --location 'localhost:4000/headlamp/config'
Image
  1. Get the admin credentials for the cluster using kubelogin
kubelogin get-token --login azurecli --server-id <your-server-id>

Note: server-id can be retrieved from the kubeconfig exec

  1. Use the admin token to fetch pods and services from default namespace
curl --location 'http://localhost:4000/headlamp/clusters/main/api/v1/namespaces/default/services' \
--header 'Accept: */*' \
--header 'Authorization: Bearer <your-admin-token>' 
Image
curl --location 'http://localhost:4000/headlamp/clusters/main/api/v1/namespaces/default/pods' \
--header 'Accept: */*' \
--header 'Authorization: Bearer <your-admin-token>' 
Image

With the admin token both services and pods should be accessible

  1. Testing with Impersonation headers.
curl --location 'http://localhost:4000/headlamp/clusters/main/api/v1/namespaces/default/pods' \
--header 'Accept: */*' \
--header 'Impersonate-User: test-user2' \
--header 'Authorization: Bearer <your-admin-token>' 
Image
curl --location 'http://localhost:4000/headlamp/clusters/main/api/v1/namespaces/default/services' \
--header 'Accept: */*' \
--header 'Impersonate-User: test-user2' \
--header 'Authorization: Bearer <your-admin-token>'
Image

With user impersonation headers only pods should be accessible, services should through 403 forbidden error

This showcases that proxy that is created by headlamp to the cluster supports Impersonation out of the box.

@mlbiam If you can point me to a doc for using openunison as an oidc proxy with impersonation configurations. I will test that too.

@mlbiam
Copy link
Author

mlbiam commented Feb 26, 2025

@yolossn to deploy with entra:

  1. Deploy OpenUnison with impersonation enabled - https://openunison.github.io/deployauth/
  2. Use openID Connect with EntraID. If you want to be able to use group names in RBAC - https://openunison.github.io/identity%20providers/azuread/

Once you're able to login to your cluster, add this to your openunison values.yaml:

openunison:
  apps:
  - name: headlamp
    label: Headlamp
    org: b1bf4c92-7220-4ad2-91af-ee0fe0af7312
    badgeUrl: https://headlamp-ingress.domain.com/
    injectToken: true
    proxyTo: http://healamp.headlamp.svc${fullURI}
    azGroup:
    - group_from_entraid
    icon: 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dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIgogICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICAgeG1sbnM6R0lNUD0iaHR0cDovL3d3dy5naW1wLm9yZy94bXAvIgogICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iCiAgIHhtcE1NOkRvY3VtZW50SUQ9ImdpbXA6ZG9jaWQ6Z2ltcDpkYjhlYTRhMS1iN2U4LTQyZjItOGMxYy0zNDgxZDQ0YWY1NTYiCiAgIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MmE5YzE1NTctZTExMS00N2QxLWE5ZDMtZTY5MDgxY2NhMjJmIgogICB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6ZTJiZjljOGEtOTc5My00ZTk1LWIxNDMtM2U5NDBmMjk4NjcyIgogICBkYzpGb3JtYXQ9ImltYWdlL3BuZyIKICAgR0lNUDpBUEk9IjIuMCIKICAgR0lNUDpQbGF0Zm9ybT0iTWFjIE9TIgogICBHSU1QOlRpbWVTdGFtcD0iMTc0MDUzNDM2Mjg3MDM2OSIKICAgR0lNUDpWZXJzaW9uPSIyLjEwLjI4IgogICB0aWZmOk9yaWVudGF0aW9uPSIxIgogICB4bXA6Q3JlYXRvclRvb2w9IkdJTVAgMi4xMCI+CiAgIDx4bXBNTTpIaXN0b3J5PgogICAgPHJkZjpTZXE+CiAgICAgPHJkZjpsaQogICAgICBzdEV2dDphY3Rpb249InNhdmVkIgogICAgICBzdEV2dDpjaGFuZ2VkPSIvIgogICAgICBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjZlMmI3MDRhLWQzN2QtNGE3Yi04NjRhLWFlZjFjZTRjMjBlMCIKICAgICAgc3RFdnQ6c29mdHdhcmVBZ2VudD0iR2ltcCAyLjEwIChNYWMgT1MpIgogICAgICBzdEV2dDp3aGVuPSIyMDI1LTAyLTI1VDIwOjQ2OjAyLTA1OjAwIi8+CiAgICA8L3JkZjpTZXE+CiAgIDwveG1wTU06SGlzdG9yeT4KICA8L3JkZjpEZXNjcmlwdGlvbj4KIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAKPD94cGFja2V0IGVuZD0idyI/PpSPVkAAAAAGYktHRAD/AP8A/6C9p5MAAAAJcEhZcwAALiMAAC4jAXilP3YAAAAHdElNRQfpAhoBLgJcMAZGAAAgAElEQVR42u2deZRcxXX/P7fqvdc9qxYkgRC7EEhgsTkW4hcg4ZDgDesX5PUYfkbegBA5sWPsY2x8gAQb84sJEIJjMDLewmJAYBsDBhsTMEsAAUImAqPFBgYhCSSNZuvu917d3x+vuxmI84sdMzPd4n7OqTM9I810v6r6Vt26desWGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGIZhGEabIVYFrz8XXHDBgksuueQjlUqFUqmEqrbcZzziiCP8TTfd9HFrrdeHyKrg9Wfbtm37bdiw4VQRQVVbUkgvvfQSgAnJhNTC03xdQN578jxHpPUm/hCCNZQJqbUJISAi5HnekrMRQBzH1lCvI86qYAwq1bmWFVCDPM+toUxIhmFCMgwTkmEYJiTDMCEZhgnJMExIhmGYkAzDhGQYJiTDMCEZhmFCmjB6enqmiUhLRn03GBwc5PHHH59irfX6YAf7XiduvfXWnXp7e8+47rrrTn744YdnPvLII4QQWva4QrlcZuHChSMnn3zywIYNG+affPLJtVmzZm2z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

Then update the orchestra-login-portal chart, no need to restart anything.

Create an Ingress object for headlamp-ingress.domain.com

Login to OpenUnison, there will now be a Headlamp badge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend Issues related to the backend blocker Completely prevents the user from using the software. oidc Issue related to OIDC security
Projects
Development

No branches or pull requests

7 participants