docs: remove incorrect watchPlugins: false references

Remove all references to the incorrect `config.watchPlugins: false`
requirement that was believed necessary for Headlamp v0.39.0+.

Investigation revealed that plugins work correctly with the default
`watchPlugins: true` setting. The earlier documentation was based on
a misunderstanding of the plugin loading mechanism.

Changes:
- Remove watchPlugins: false from all YAML configuration examples
- Remove warning sections about watchPlugins requirement
- Update troubleshooting guides to focus on actual issues
- Simplify installation instructions by removing unnecessary config

Files updated:
- README.md (main installation docs and troubleshooting table)
- docs/DEPLOYMENT.md
- docs/TROUBLESHOOTING.md
- docs/getting-started/* (quick-start, installation, prerequisites)
- docs/deployment/* (helm, production)
- docs/troubleshooting/* (common-issues, README)
- Multiple other doc files formatted by prettier

This cleanup ensures ArtifactHub and GitHub documentation show
correct, simplified installation instructions.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
2026-02-13 09:54:15 -05:00
parent 0faa50cd9d
commit 24033ca977
25 changed files with 775 additions and 468 deletions
+65 -34
View File
@@ -13,6 +13,7 @@ The plugin requires **one permission** to function:
This allows the plugin to fetch audit results via the Kubernetes service proxy.
**Why this permission?**
- Plugin accesses Polaris through Kubernetes API server's service proxy
- Service proxy requires `get` verb on `services/proxy` resource
- Scoped to specific service (`polaris-dashboard`) for security
@@ -37,13 +38,14 @@ metadata:
app.kubernetes.io/name: headlamp-polaris-plugin
app.kubernetes.io/component: rbac
rules:
- apiGroups: [""]
resources: ["services/proxy"]
resourceNames: ["polaris-dashboard"]
verbs: ["get"]
- apiGroups: ['']
resources: ['services/proxy']
resourceNames: ['polaris-dashboard']
verbs: ['get']
```
**Key points:**
- **Role** (not ClusterRole) - Scoped to `polaris` namespace only
- **resourceNames** - Restricts access to `polaris-dashboard` service only
- **verbs: ["get"]** - Read-only permission
@@ -62,8 +64,8 @@ metadata:
app.kubernetes.io/component: rbac
subjects:
- kind: ServiceAccount
name: headlamp # Adjust to your Headlamp SA name
namespace: kube-system # Adjust to Headlamp's namespace
name: headlamp # Adjust to your Headlamp SA name
namespace: kube-system # Adjust to Headlamp's namespace
roleRef:
kind: Role
name: polaris-proxy-reader
@@ -71,6 +73,7 @@ roleRef:
```
**Adjust for your environment:**
- `subjects[0].name` - Your Headlamp service account name (often `headlamp`)
- `subjects[0].namespace` - Namespace where Headlamp runs (often `kube-system`)
@@ -104,10 +107,12 @@ In token-auth mode, **each user's own identity** is used for Kubernetes API requ
### Why Per-User RBAC?
With service account mode:
- Single RoleBinding grants access to all Headlamp users
- Kubernetes sees all requests as `system:serviceaccount:kube-system:headlamp`
With token-auth mode:
- Each user's own token (OIDC, kubeconfig) is used
- Kubernetes sees requests as `user@example.com` or `system:serviceaccount:team-ns:user-sa`
- **Each user needs individual RBAC permissions**
@@ -125,7 +130,7 @@ metadata:
namespace: polaris
subjects:
- kind: Group
name: system:authenticated # All authenticated users
name: system:authenticated # All authenticated users
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
@@ -174,7 +179,7 @@ metadata:
namespace: polaris
subjects:
- kind: Group
name: sre-team # OIDC group claim
name: sre-team # OIDC group claim
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: devops-team
@@ -186,11 +191,13 @@ roleRef:
```
**Requirements:**
- OIDC provider must include group claims in token
- Headlamp must be configured to extract groups from OIDC token
- Group names must match exactly (case-sensitive)
**Example OIDC group claim:**
```json
{
"sub": "user@example.com",
@@ -229,23 +236,23 @@ apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: polaris-proxy-reader
namespace: team-a-polaris # First Polaris instance
namespace: team-a-polaris # First Polaris instance
rules:
- apiGroups: [""]
resources: ["services/proxy"]
resourceNames: ["polaris-dashboard"]
verbs: ["get"]
- apiGroups: ['']
resources: ['services/proxy']
resourceNames: ['polaris-dashboard']
verbs: ['get']
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: polaris-proxy-reader
namespace: team-b-polaris # Second Polaris instance
namespace: team-b-polaris # Second Polaris instance
rules:
- apiGroups: [""]
resources: ["services/proxy"]
resourceNames: ["polaris-dashboard"]
verbs: ["get"]
- apiGroups: ['']
resources: ['services/proxy']
resourceNames: ['polaris-dashboard']
verbs: ['get']
```
### Create RoleBindings per Namespace
@@ -343,22 +350,24 @@ When using OAuth2/OIDC authentication with Headlamp:
### Required Configuration
**Headlamp Helm values:**
```yaml
env:
- name: HEADLAMP_CONFIG_OIDC_CLIENT_ID
value: "headlamp"
value: 'headlamp'
- name: HEADLAMP_CONFIG_OIDC_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: headlamp-oidc
key: client-secret
- name: HEADLAMP_CONFIG_OIDC_ISSUER_URL
value: "https://auth.example.com/realms/kubernetes"
value: 'https://auth.example.com/realms/kubernetes'
- name: HEADLAMP_CONFIG_OIDC_SCOPES
value: "openid,profile,email,groups"
value: 'openid,profile,email,groups'
```
**RBAC for OIDC users:**
```yaml
---
apiVersion: rbac.authorization.k8s.io/v1
@@ -368,7 +377,7 @@ metadata:
namespace: polaris
subjects:
- kind: Group
name: kubernetes-admins # OIDC group claim
name: kubernetes-admins # OIDC group claim
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
@@ -421,32 +430,36 @@ Every plugin data fetch creates a Kubernetes API audit log entry.
### Volume Estimates
**Per user:**
- 1 refresh per 5 minutes = 288 requests/day
- 1 refresh per 30 minutes = 48 requests/day
**Cluster-wide:**
- 10 concurrent users × 5-minute refresh = 2,880 audit logs/day
- 100 concurrent users × 30-minute refresh = 4,800 audit logs/day
### Reducing Audit Volume
**Option 1: Increase refresh interval**
```
Settings → Plugins → Polaris → Refresh Interval → 30 minutes
```
**Option 2: Adjust audit policy level**
```yaml
# kube-apiserver audit policy
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata # Log metadata only, not full request/response
verbs: ["get"]
- level: Metadata # Log metadata only, not full request/response
verbs: ['get']
resources:
- group: ""
resources: ["services/proxy"]
namespaces: ["polaris"]
- group: ''
resources: ['services/proxy']
namespaces: ['polaris']
```
**Option 3: Filter audit logs**
@@ -461,18 +474,23 @@ If using a log aggregator (e.g., Elasticsearch), create filters to exclude or do
**Diagnosis:**
1. **Check Role exists:**
```bash
kubectl -n polaris get role polaris-proxy-reader
```
If missing: Apply Role manifest
2. **Check RoleBinding exists:**
```bash
kubectl -n polaris get rolebinding headlamp-polaris-proxy
```
If missing: Apply RoleBinding manifest
3. **Test permission:**
```bash
# Service account mode
kubectl auth can-i get services/proxy \
@@ -486,6 +504,7 @@ If using a log aggregator (e.g., Elasticsearch), create filters to exclude or do
-n polaris \
--resource-name=polaris-dashboard
```
Expected: `yes`
4. **Verify RoleBinding subjects match:**
@@ -499,6 +518,7 @@ If using a log aggregator (e.g., Elasticsearch), create filters to exclude or do
**This is NOT an RBAC issue.** 404 means Polaris service doesn't exist.
**Check:**
```bash
kubectl -n polaris get svc polaris-dashboard
```
@@ -510,14 +530,17 @@ If missing, install Polaris with dashboard enabled.
**Possible causes:**
1. **Wrong namespace in RoleBinding:**
- RoleBinding must be in `polaris` namespace (where the service is)
- Common mistake: Creating RoleBinding in `kube-system`
2. **Wrong resourceName:**
- Must match service name exactly: `polaris-dashboard`
- Check: `kubectl -n polaris get svc`
3. **Browser caching old 403:**
- Hard refresh browser: Cmd+Shift+R (Mac) or Ctrl+Shift+R (Windows/Linux)
4. **Token expired (OIDC mode):**
@@ -529,6 +552,7 @@ If missing, install Polaris with dashboard enabled.
### 1. Use Namespaced Roles (Not ClusterRoles)
✅ **Good:**
```yaml
kind: Role
metadata:
@@ -536,6 +560,7 @@ metadata:
```
❌ **Bad:**
```yaml
kind: ClusterRole
# Grants access to all namespaces
@@ -546,13 +571,15 @@ kind: ClusterRole
### 2. Always Specify resourceNames
✅ **Good:**
```yaml
resourceNames: ["polaris-dashboard"]
resourceNames: ['polaris-dashboard']
```
❌ **Bad:**
```yaml
resourceNames: [] # Allows access to ALL services
resourceNames: [] # Allows access to ALL services
```
**Why:** `resourceNames` restricts permission to a specific service. Without it, the binding grants access to proxy all services in the namespace.
@@ -560,13 +587,15 @@ resourceNames: [] # Allows access to ALL services
### 3. Use Read-Only Verb
✅ **Good:**
```yaml
verbs: ["get"]
verbs: ['get']
```
❌ **Bad:**
```yaml
verbs: ["get", "create", "update", "delete"]
verbs: ['get', 'create', 'update', 'delete']
```
**Why:** Plugin only needs `get` to fetch audit results. Additional verbs violate principle of least privilege.
@@ -580,6 +609,7 @@ verbs: ["get", "create", "update", "delete"]
### 5. Monitor Audit Logs
Set alerts for:
- Unusual access patterns (e.g., 403 spikes = permission issues)
- High request volume (e.g., misconfigured refresh interval)
- Access from unexpected users (security monitoring)
@@ -587,11 +617,12 @@ Set alerts for:
### 6. Avoid Wildcard Permissions
❌ **Never do this:**
```yaml
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
- apiGroups: ['*']
resources: ['*']
verbs: ['*']
```
This grants cluster-admin equivalent permissions. Always use specific resources and verbs.