Modern, production-ready Kubernetes visibility dashboard with strict application-level authorization. Runs inside Kubernetes, reads cluster data using a single ServiceAccount identity per cluster, and enforces access strictly in the app layer (no Kubernetes RBAC for end users).
- Read-only Kubernetes visibility (Pods, Deployments, Services, ConfigMaps)
- Application-level RBAC: user → groups → roles → per-namespace permissions
- Namespace discovery is permission-based (no leakage)
- JWT authentication with forced password change on first login
- Local users (bcrypt) + LDAP auth (bind-based) + Azure AD login configurable via UI
- Audit logs with pagination, filters, and CSV export
- WebSocket pod log streaming with rate limiting
- Cluster connection management via UI only (kubeconfig or token)
- Modern React + TypeScript UI
- Backend: Go +
client-go. The backend communicates directly with the Kubernetes API server using client-go. - Frontend: React + TypeScript
- Database: SQLite
- Deployment: Docker + Kubernetes manifests
cd /path/to/kubernetes-openconsole
docker build -t kubernetes-openconsole:local .Update deploy/deployment.yaml to use the published image:
image: ghcr.io/vurulkan/kubernetes-openconsole:latestdocker run --rm -p 8080:8080 \
-e LOG_RETENTION_DAYS=30 \
-e TIMEZONE=Europe/Istanbul \
-e DATA_PATH=/data/app.db \
-e STATIC_DIR=/app/public \
-v kubernetes-openconsole-data:/data \
kubernetes-openconsole:localIf you prefer ephemeral storage: set
DATA_PATH=/tmp/app.dbwithout a volume mount.
Apply manifests in deploy/:
kubectl apply -f deploy/namespace.yaml
kubectl apply -f deploy/pvc.yaml
kubectl apply -f deploy/deployment.yaml
kubectl apply -f deploy/service.yamlLOG_RETENTION_DAYS(default: 30)
Audit log retention in days (purged automatically). Set directly indeploy/deployment.yaml.TIMEZONE(default: UTC)
Used for audit log timestamps.DATA_PATH(default:/data/app.db)
SQLite DB location.STATIC_DIR(default:/app/public)
Served React build output.
Kubernetes OpenConsole runs with a single cluster identity and enforces authorization strictly at the application layer.
It does not act as a Kubernetes security boundary.
It only reflects the permissions granted to its ServiceAccount.
Below is the recommended setup using a dedicated ServiceAccount in the kubernetes-openconsole namespace.
⚠️ Quick Start (In-Cluster Default)If OpenConsole is deployed inside the same Kubernetes cluster it will monitor, it can automatically use the in-cluster configuration via the mounted ServiceAccount token (typically the default ServiceAccount).
In that case, you may skip the kubeconfig generation steps below and proceed directly to:
⚠️ While this works for quick testing, it is not recommended for production.For production environments it is strongly recommended to:
- Create a dedicated ServiceAccount
- Assign a minimal read-only ClusterRole
- Avoid granting permissions to the default ServiceAccount
This reduces blast radius and aligns with least-privilege principles.
kubectl create serviceaccount openconsole-reader -n kubernetes-openconsoleCreate openconsole-clusterrole.yaml:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: openconsole-readonly
rules:
- apiGroups: [""]
resources:
- namespaces
- pods
- services
- configmaps
- events
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources:
- pods/log
verbs: ["get"]
- apiGroups: ["apps"]
resources:
- deployments
verbs: ["get", "list", "watch"]
- apiGroups: ["networking.k8s.io"]
resources:
- ingresses
verbs: ["get", "list", "watch"]
- apiGroups: ["batch"]
resources:
- cronjobs
verbs: ["get", "list", "watch"]Apply it:
kubectl apply -f openconsole-clusterrole.yamlkubectl create clusterrolebinding openconsole-readonly-binding \
--clusterrole=openconsole-readonly \
--serviceaccount=kubernetes-openconsole:openconsole-readerkubectl create token openconsole-reader \
-n kubernetes-openconsole \
--duration=8760h8760h = 1 year. Adjust as needed.
apiVersion: v1
kind: Config
clusters:
- name: target-cluster
cluster:
server: https://YOUR_API_SERVER # from your kubeconfig
certificate-authority-data: YOUR_CA_DATA # from your kubeconfig
users:
- name: openconsole-reader
user:
token: YOUR_GENERATED_TOKEN # previous step
contexts:
- name: openconsole-context
context:
cluster: target-cluster
user: openconsole-reader
current-context: openconsole-context...
metadata:
labels:
app: kubernetes-openconsole
spec:
serviceAccountName: openconsole-reader # -> add this line
securityContext:
runAsNonRoot: true
...- This ServiceAccount is read-only
- It cannot:
- exec into pods
- port-forward
- read secrets
- modify resources
- Token rotation is recommended (every 6–12 months)
- Do not store generated tokens in Git
- Prefer one ServiceAccount per cluster
- OpenConsole does not bypass Kubernetes RBAC; it operates strictly within the permissions granted to its ServiceAccount.
- One ServiceAccount per cluster
- One kubeconfig per cluster
- Store tokens securely
- Rotate periodically
- Avoid using personal user credentials
On first startup a default admin is created:
- username:
admin - password:
admin
You will be forced to change the password on first login.
- Log in as admin.
- Admin → Cluster: upload kubeconfig or token, validate, apply.
- Admin → LDAP / Azure AD: configure optional identity providers.
- Admin → Users/Groups/Roles: define access.
- Admin → Audit Logs: filter, search, export CSV.
Replace the values with your environment. The example below is anonymized.
- host:
10.10.20.15 - port:
389 - skip verify:
false - bind dn:
CN=svc-openconsole,OU=ServiceAccounts,OU=IT,DC=example,DC=corp - bind password:
******** - user base dn:
OU=Engineering,OU=Users,DC=example,DC=corp - user filter:
(sAMAccountName=%s*)
Azure AD is supported as an additional login method and can run in parallel with local/LDAP authentication.
- Azure AD login is configured from Admin → Azure AD.
- On first successful Azure AD login, the user is automatically created in the local database.
- RBAC still uses the same local model (Users → Groups → Roles).
- Logout is application-local only (does not sign out globally from Microsoft).
- Tenant type: Single tenant
- Redirect URI:
https://<your-domain>/api/auth/azure/callback - Scopes used by app:
openid profile email
After first login, assign groups/roles in Admin → Users/Groups/Roles to grant namespace/resource access.
- Cluster connection is UI-only. No env vars or mounted kubeconfigs.
- Namespace visibility is permission-based; if a user sees nothing, check role permissions.
- If LDAP bind password is already configured, toggle Update Bind Password only when changing it.
- Audit log filters can combine user/action/namespace/date range.
- Pod logs stream via WebSocket; verify connectivity from the backend pod to the API server.
Kubernetes OpenConsole is designed as an internal visibility platform and is not a Kubernetes security boundary.