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:
@@ -28,12 +28,14 @@ Access plugin settings via **Settings → Plugins → Polaris** in the Headlamp
|
||||
### Impact
|
||||
|
||||
**Affects:**
|
||||
|
||||
- Dashboard overview page
|
||||
- Namespace list and detail views
|
||||
- Inline audit sections on resource pages
|
||||
- App bar score badge
|
||||
|
||||
**API Load:**
|
||||
|
||||
- Each refresh triggers one HTTP GET to Polaris dashboard
|
||||
- Each request is logged in Kubernetes audit logs
|
||||
- Longer intervals reduce API server and audit log pressure
|
||||
@@ -41,16 +43,19 @@ Access plugin settings via **Settings → Plugins → Polaris** in the Headlamp
|
||||
### Performance Considerations
|
||||
|
||||
**For small clusters (<100 pods):**
|
||||
|
||||
- Recommended: 5 minutes (default)
|
||||
- Acceptable: 1 minute (if real-time data is critical)
|
||||
|
||||
**For large clusters (>1000 pods):**
|
||||
|
||||
- Recommended: 10-30 minutes
|
||||
- Reason: Reduces audit log volume and API server load
|
||||
- Example: 10 users × 1-minute refresh = ~14,400 audit logs/day
|
||||
- Example: 10 users × 30-minute refresh = ~480 audit logs/day
|
||||
|
||||
**For production environments:**
|
||||
|
||||
- Start with 5 minutes
|
||||
- Monitor API server metrics and audit log volume
|
||||
- Increase interval if needed
|
||||
@@ -62,6 +67,7 @@ Access plugin settings via **Settings → Plugins → Polaris** in the Headlamp
|
||||
### Default Configuration
|
||||
|
||||
**Service proxy path (default):**
|
||||
|
||||
```
|
||||
/api/v1/namespaces/polaris/services/polaris-dashboard:80/proxy/
|
||||
```
|
||||
@@ -69,6 +75,7 @@ Access plugin settings via **Settings → Plugins → Polaris** in the Headlamp
|
||||
This uses the Kubernetes API server to proxy requests to the Polaris dashboard service in the `polaris` namespace.
|
||||
|
||||
**Advantages:**
|
||||
|
||||
- Uses existing Headlamp authentication (service account or user token)
|
||||
- Works with Headlamp's OIDC and token-auth modes
|
||||
- No additional RBAC or network configuration needed
|
||||
@@ -85,6 +92,7 @@ https://polaris.example.com/
|
||||
```
|
||||
|
||||
**Requirements:**
|
||||
|
||||
- Polaris dashboard must be accessible from browser
|
||||
- CORS must be configured on Polaris to allow Headlamp origin
|
||||
- HTTPS recommended for production
|
||||
@@ -98,6 +106,7 @@ If Polaris is deployed in a different namespace:
|
||||
```
|
||||
|
||||
**Requirements:**
|
||||
|
||||
- Update RBAC Role namespace to match
|
||||
- Service name must still be `polaris-dashboard` (or adjust in URL)
|
||||
|
||||
@@ -131,39 +140,43 @@ http://localhost:8080/
|
||||
**What it does:** Verifies the plugin can reach the Polaris dashboard and fetch audit data.
|
||||
|
||||
**To test:**
|
||||
|
||||
1. Enter Dashboard URL in settings
|
||||
2. Click **Test Connection**
|
||||
3. Wait for response (2-5 seconds)
|
||||
|
||||
**Success Response:**
|
||||
|
||||
```
|
||||
✓ Connected to Polaris v4.2.0
|
||||
```
|
||||
|
||||
**Error Responses:**
|
||||
|
||||
| Error | Meaning | Solution |
|
||||
|-------|---------|----------|
|
||||
| **403 Forbidden** | RBAC permission denied | Check RBAC bindings (see [RBAC Guide](rbac-permissions.md)) |
|
||||
| **404 Not Found** | Polaris service not found | Verify Polaris is running: `kubectl get svc -n polaris` |
|
||||
| **503 Service Unavailable** | Polaris pod not ready | Check pod status: `kubectl get pods -n polaris` |
|
||||
| **Network Error** | Cannot reach URL | Check URL format, CORS (for external), NetworkPolicies |
|
||||
| **CORS Error** | Cross-origin blocked | Configure Polaris dashboard CORS headers |
|
||||
| Error | Meaning | Solution |
|
||||
| --------------------------- | ------------------------- | ----------------------------------------------------------- |
|
||||
| **403 Forbidden** | RBAC permission denied | Check RBAC bindings (see [RBAC Guide](rbac-permissions.md)) |
|
||||
| **404 Not Found** | Polaris service not found | Verify Polaris is running: `kubectl get svc -n polaris` |
|
||||
| **503 Service Unavailable** | Polaris pod not ready | Check pod status: `kubectl get pods -n polaris` |
|
||||
| **Network Error** | Cannot reach URL | Check URL format, CORS (for external), NetworkPolicies |
|
||||
| **CORS Error** | Cross-origin blocked | Configure Polaris dashboard CORS headers |
|
||||
|
||||
### CORS Configuration (External Polaris)
|
||||
|
||||
If using an external Polaris URL, configure CORS to allow Headlamp origin.
|
||||
|
||||
**Polaris Helm values:**
|
||||
|
||||
```yaml
|
||||
dashboard:
|
||||
enabled: true
|
||||
env:
|
||||
- name: CORS_ALLOWED_ORIGINS
|
||||
value: "https://headlamp.example.com"
|
||||
value: 'https://headlamp.example.com'
|
||||
```
|
||||
|
||||
**Test CORS:**
|
||||
|
||||
```bash
|
||||
curl -v -H "Origin: https://headlamp.example.com" \
|
||||
https://polaris.example.com/results.json \
|
||||
@@ -180,25 +193,29 @@ curl -v -H "Origin: https://headlamp.example.com" \
|
||||
Plugin settings are stored in browser **localStorage**:
|
||||
|
||||
**Keys:**
|
||||
|
||||
- `polaris-plugin-refresh-interval` - Refresh interval in seconds (number)
|
||||
- `polaris-plugin-dashboard-url` - Dashboard URL (string)
|
||||
|
||||
**View settings:**
|
||||
|
||||
```javascript
|
||||
// Open browser DevTools Console (F12)
|
||||
console.log('Refresh Interval:', localStorage.getItem('polaris-plugin-refresh-interval'))
|
||||
console.log('Dashboard URL:', localStorage.getItem('polaris-plugin-dashboard-url'))
|
||||
console.log('Refresh Interval:', localStorage.getItem('polaris-plugin-refresh-interval'));
|
||||
console.log('Dashboard URL:', localStorage.getItem('polaris-plugin-dashboard-url'));
|
||||
```
|
||||
|
||||
**Reset to defaults:**
|
||||
|
||||
```javascript
|
||||
// Open browser DevTools Console (F12)
|
||||
localStorage.removeItem('polaris-plugin-refresh-interval')
|
||||
localStorage.removeItem('polaris-plugin-dashboard-url')
|
||||
localStorage.removeItem('polaris-plugin-refresh-interval');
|
||||
localStorage.removeItem('polaris-plugin-dashboard-url');
|
||||
// Hard refresh browser: Cmd+Shift+R (Mac) or Ctrl+Shift+R (Windows/Linux)
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
|
||||
- Settings are per-browser, per-user
|
||||
- Private/incognito mode may clear settings on browser close
|
||||
- Settings are NOT synced across devices
|
||||
@@ -208,6 +225,7 @@ localStorage.removeItem('polaris-plugin-dashboard-url')
|
||||
### For Development Clusters
|
||||
|
||||
**Recommended Settings:**
|
||||
|
||||
- **Refresh Interval:** 1-5 minutes (faster feedback loop)
|
||||
- **Dashboard URL:** Service proxy (default)
|
||||
|
||||
@@ -216,6 +234,7 @@ localStorage.removeItem('polaris-plugin-dashboard-url')
|
||||
### For Staging Clusters
|
||||
|
||||
**Recommended Settings:**
|
||||
|
||||
- **Refresh Interval:** 5-10 minutes (balanced)
|
||||
- **Dashboard URL:** Service proxy (default)
|
||||
|
||||
@@ -224,6 +243,7 @@ localStorage.removeItem('polaris-plugin-dashboard-url')
|
||||
### For Production Clusters
|
||||
|
||||
**Recommended Settings:**
|
||||
|
||||
- **Refresh Interval:** 10-30 minutes (reduce load)
|
||||
- **Dashboard URL:** Service proxy (default)
|
||||
|
||||
@@ -232,6 +252,7 @@ localStorage.removeItem('polaris-plugin-dashboard-url')
|
||||
### For Multi-Tenant Environments
|
||||
|
||||
**Recommended Settings:**
|
||||
|
||||
- **Refresh Interval:** 10-30 minutes (minimize per-user load)
|
||||
- **Dashboard URL:** Service proxy with per-namespace RBAC
|
||||
|
||||
@@ -240,6 +261,7 @@ localStorage.removeItem('polaris-plugin-dashboard-url')
|
||||
### For External Polaris
|
||||
|
||||
**Recommended Settings:**
|
||||
|
||||
- **Refresh Interval:** 5-10 minutes (depends on network latency)
|
||||
- **Dashboard URL:** `https://polaris.example.com/`
|
||||
- **CORS:** Must be configured on Polaris side
|
||||
@@ -253,17 +275,19 @@ localStorage.removeItem('polaris-plugin-dashboard-url')
|
||||
**Symptom:** Changes to settings revert after clicking Save
|
||||
|
||||
**Possible Causes:**
|
||||
|
||||
1. Browser blocks localStorage (privacy mode)
|
||||
2. Browser extension interfering
|
||||
3. JavaScript error in console
|
||||
|
||||
**Solution:**
|
||||
|
||||
1. Open browser DevTools Console (F12)
|
||||
2. Check for JavaScript errors
|
||||
3. Disable privacy mode or try different browser
|
||||
4. Check if localStorage is enabled:
|
||||
```javascript
|
||||
console.log('localStorage available:', typeof localStorage !== 'undefined')
|
||||
console.log('localStorage available:', typeof localStorage !== 'undefined');
|
||||
```
|
||||
|
||||
### Settings Lost After Browser Restart
|
||||
@@ -273,6 +297,7 @@ localStorage.removeItem('polaris-plugin-dashboard-url')
|
||||
**Cause:** Browser privacy settings clear localStorage on exit
|
||||
|
||||
**Solution:**
|
||||
|
||||
- Use normal browsing mode (not private/incognito)
|
||||
- Check browser settings for "Clear data on exit"
|
||||
- Consider requesting ConfigMap-based settings (future feature)
|
||||
@@ -284,6 +309,7 @@ localStorage.removeItem('polaris-plugin-dashboard-url')
|
||||
**Solutions by error type:**
|
||||
|
||||
**403 Forbidden:**
|
||||
|
||||
```bash
|
||||
# Verify RBAC exists
|
||||
kubectl -n polaris get role polaris-proxy-reader
|
||||
@@ -297,6 +323,7 @@ kubectl auth can-i get services/proxy \
|
||||
```
|
||||
|
||||
**404 Not Found:**
|
||||
|
||||
```bash
|
||||
# Verify Polaris is running
|
||||
kubectl -n polaris get pods
|
||||
@@ -310,6 +337,7 @@ helm install polaris fairwinds-stable/polaris \
|
||||
```
|
||||
|
||||
**503 Service Unavailable:**
|
||||
|
||||
```bash
|
||||
# Check pod status
|
||||
kubectl -n polaris get pods
|
||||
@@ -319,6 +347,7 @@ kubectl -n polaris logs deployment/polaris-dashboard
|
||||
```
|
||||
|
||||
**Network Error / CORS:**
|
||||
|
||||
```bash
|
||||
# For external Polaris, test CORS
|
||||
curl -v -H "Origin: https://headlamp.example.com" \
|
||||
@@ -332,15 +361,17 @@ curl -v -H "Origin: https://headlamp.example.com" \
|
||||
**Symptom:** Data doesn't refresh automatically
|
||||
|
||||
**Check:**
|
||||
|
||||
1. Verify setting is saved (localStorage key exists)
|
||||
2. Check browser console for errors
|
||||
3. Verify Polaris is returning data (manual refresh works)
|
||||
4. Ensure you're on a Polaris plugin page (not other Headlamp pages)
|
||||
|
||||
**Debug:**
|
||||
|
||||
```javascript
|
||||
// Check refresh interval
|
||||
console.log(localStorage.getItem('polaris-plugin-refresh-interval'))
|
||||
console.log(localStorage.getItem('polaris-plugin-refresh-interval'));
|
||||
|
||||
// Should return: "300" (5 minutes), "600" (10 minutes), etc.
|
||||
```
|
||||
@@ -361,6 +392,7 @@ Before going to production, verify:
|
||||
## Future Configuration Options
|
||||
|
||||
**Planned features:**
|
||||
|
||||
- ConfigMap-based settings (server-side, not localStorage)
|
||||
- Per-cluster settings (multi-cluster Headlamp support)
|
||||
- Webhook notifications for score changes
|
||||
|
||||
@@ -58,6 +58,7 @@ Click the refresh button to fetch the latest audit data immediately (bypasses au
|
||||
Navigate to **Polaris → Namespaces** to see all namespaces with audit results.
|
||||
|
||||
**Table Columns:**
|
||||
|
||||
- **Namespace** - Clickable namespace name (opens detail panel)
|
||||
- **Score** - Per-namespace score with color coding
|
||||
- **Pass** - Passing checks count
|
||||
@@ -72,6 +73,7 @@ Navigate to **Polaris → Namespaces** to see all namespaces with audit results.
|
||||
Click any namespace to open a 1000px-wide side panel with detailed information.
|
||||
|
||||
**Features:**
|
||||
|
||||
- **Namespace Score** - Color-coded score gauge
|
||||
- **Check Counts** - Pass/Warning/Danger/Skipped breakdown
|
||||
- **Resource Table** - Per-resource audit results:
|
||||
@@ -92,6 +94,7 @@ Polaris audit results automatically appear on resource detail pages.
|
||||
### Supported Resources
|
||||
|
||||
Inline audit sections appear on:
|
||||
|
||||
- Deployments
|
||||
- StatefulSets
|
||||
- DaemonSets
|
||||
@@ -101,6 +104,7 @@ Inline audit sections appear on:
|
||||
### What's Shown
|
||||
|
||||
**Compact Audit Section:**
|
||||
|
||||
- **Score Badge** - Color-coded score
|
||||
- **Check Counts** - Pass/Warning/Danger summary
|
||||
- **Failing Checks Table** - Only failed checks listed:
|
||||
@@ -116,6 +120,7 @@ Inline audit sections appear on:
|
||||
Top-right corner of Headlamp shows a persistent cluster score badge.
|
||||
|
||||
**Features:**
|
||||
|
||||
- **Color-Coded Chip** - Green/Yellow/Red based on score
|
||||
- **Shield Icon** - Visual indicator
|
||||
- **Score Percentage** - e.g., "85%"
|
||||
@@ -134,12 +139,14 @@ Access plugin settings via **Settings → Plugins → Polaris**.
|
||||
Controls how often the plugin fetches new audit data.
|
||||
|
||||
**Options:**
|
||||
|
||||
- 1 minute - Most frequent (highest API load)
|
||||
- 5 minutes - **Default** (recommended)
|
||||
- 10 minutes - Moderate refresh rate
|
||||
- 30 minutes - Light load (large clusters)
|
||||
|
||||
**Impact:**
|
||||
|
||||
- Affects all views (dashboard, namespaces, inline audits, app bar badge)
|
||||
- Longer intervals reduce Kubernetes API audit logging
|
||||
- Changes take effect immediately (no restart required)
|
||||
@@ -151,11 +158,13 @@ See [Configuration Guide](configuration.md) for details.
|
||||
Specifies which Polaris instance to connect to.
|
||||
|
||||
**Default:** Kubernetes service proxy path
|
||||
|
||||
```
|
||||
/api/v1/namespaces/polaris/services/polaris-dashboard:80/proxy/
|
||||
```
|
||||
|
||||
**Custom Options:**
|
||||
|
||||
- External Polaris: `https://polaris.example.com/`
|
||||
- Different namespace: `/api/v1/namespaces/custom-ns/services/polaris-dashboard:80/proxy/`
|
||||
|
||||
@@ -168,6 +177,7 @@ See [Configuration Guide](configuration.md) for advanced setup.
|
||||
Full theme adaptation for Headlamp's light and dark modes.
|
||||
|
||||
**Features:**
|
||||
|
||||
- **Auto Dark Mode** - Respects system preference when Headlamp uses it
|
||||
- **Theme Toggle** - Adapts when you change Headlamp theme
|
||||
- **All UI Elements** - Drawer backgrounds, tables, buttons, badges, score gauge
|
||||
@@ -180,6 +190,7 @@ Full theme adaptation for Headlamp's light and dark modes.
|
||||
**Status:** Planned feature (UI components exist but not fully integrated)
|
||||
|
||||
**Future Capability:**
|
||||
|
||||
- View current exemptions on resources
|
||||
- Add exemptions for specific failing checks
|
||||
- Remove exemptions
|
||||
@@ -190,21 +201,25 @@ This feature requires additional RBAC permissions (PATCH on workload resources)
|
||||
## Data Refresh Behavior
|
||||
|
||||
**Initial Load:**
|
||||
|
||||
- Data fetched when you first navigate to any Polaris view
|
||||
- Shared across all views via React Context (no duplicate fetches)
|
||||
- Loading spinner displayed during initial fetch
|
||||
|
||||
**Auto-Refresh:**
|
||||
|
||||
- Configured via Settings → Plugins → Polaris
|
||||
- Default: 5 minutes
|
||||
- Triggers background fetch without disrupting UI
|
||||
|
||||
**Manual Refresh:**
|
||||
|
||||
- Click refresh button on overview dashboard
|
||||
- Forces immediate data fetch
|
||||
- Updates all views simultaneously
|
||||
|
||||
**Error Handling:**
|
||||
|
||||
- 403 errors show RBAC permission guidance
|
||||
- 404/503 errors indicate Polaris not installed
|
||||
- Network errors show generic failure with retry suggestion
|
||||
@@ -212,12 +227,14 @@ This feature requires additional RBAC permissions (PATCH on workload resources)
|
||||
## Browser Requirements
|
||||
|
||||
**Supported Browsers:**
|
||||
|
||||
- Chrome/Chromium 80+
|
||||
- Firefox 75+
|
||||
- Safari 13.1+
|
||||
- Edge 80+
|
||||
|
||||
**Required:**
|
||||
|
||||
- JavaScript enabled
|
||||
- localStorage enabled (for settings persistence)
|
||||
- Cookies enabled (for Headlamp session)
|
||||
@@ -227,11 +244,13 @@ This feature requires additional RBAC permissions (PATCH on workload resources)
|
||||
**Bundle Size:** ~27 KB minified (gzip: ~7.6 KB)
|
||||
|
||||
**Data Volume:** Depends on cluster size. Example:
|
||||
|
||||
- Small cluster (50 resources): ~100 KB JSON
|
||||
- Medium cluster (500 resources): ~1 MB JSON
|
||||
- Large cluster (5000 resources): ~10 MB JSON
|
||||
|
||||
**Rendering Performance:**
|
||||
|
||||
- Handles up to 100 namespaces without virtual scrolling
|
||||
- Namespace detail drawer renders instantly for up to 500 resources
|
||||
- React Context prevents unnecessary re-fetches
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user