0020: The published console, and port-forwards without an Access login¶
Date: 2026-10-13 · Status: accepted
Context¶
The design puts the console behind Cloudflare Tunnel and Access, so that people without cluster access can use it.
The chart accepted expose.cloudflared.consoleHostname, but nothing published it: an administrator had to create
the Access application, its DNS record and the tunnel route by hand, then copy the application's audience tag and
the team domain into the chart. Meanwhile people with cluster access used tenax console, a port-forward to
tenax-api. Once tenax-api verifies Access tokens, a port-forward carries none and is refused.
Decision¶
- Tenax publishes the console. With
expose.provider: cloudflareand aconsoleHostname, the controller creates and keeps (re-checked every 15 minutes) an Access application for the hostname with the sandbox routes' rules (allowEmails,allowGroups; a changed list updates it), a proxied CNAME to the tunnel and the tunnel route to the tenax-api Service. The only credential is still the one API token. - tenax-api learns how to verify tokens from the controller. The controller writes the application's
audience tag and the team domain to the Secret
<release>-console-access; tenax-api mounts it (optional) and re-reads it as it changes. Until it exists every request is refused with "console login not ready". Keys, cached tokens and issuers are tied to the team domain, so a changed team never accepts the old team's tokens. The team domain comes fromauth.cloudflareAccess.teamDomainwhen set, else from the account's Access organization (Access: Organizations Read), else from the*.cloudflareaccess.comlogin redirect Access sends for an anonymous request to the console. - Port-forwards get their own port. With
auth.provider: cloudflare-access, tenax-api also listens on127.0.0.1:8444(container portlocal, not in the Service). Onlykubectl port-forwardreaches a pod's loopback address, so Kubernetes RBAC (pods/portforwardin Tenax's namespace) has already decided who may connect; requests there getauth.portForwardRole(defaultrestorer-admin, empty turns it off) and are audited askubectl-port-forward. The address must be a loopback one or tenax-api refuses to start.tenax consoleforwards tolocalwhen the pod has it.
Consequences¶
- An administrator sets a hostname and the email rules; people open
https://<hostname>or runtenax login --server https://<hostname>, with no kubeconfig and no values to copy from Cloudflare. - People with cluster access keep using
tenax console. Anyone who may port-forward into Tenax's namespace getsportForwardRole, so that permission must be granted as carefully as the role itself. auth.provider: cloudflare-accesswithout a team domain and audience now fails at render time unless Tenax publishes the console; before, tenax-api failed at start.- A console route an administrator made by hand on the same hostname is taken over (its application's rules are replaced by Tenax's).