Files
headlamp-tns-csi-plugin/SECURITY.md
T
Chris Farhood f1feb5c2f7 feat: native Headlamp integration, TrueNAS API, docs, and CI for v0.2.0
Native Headlamp integrations:
- registerResourceTableColumnsProcessor: add Protocol/Pool/Server columns to
  native StorageClass table and Protocol/Volume Handle to PV table
- registerDetailsViewSection: inject TNS-CSI section into PV detail pages
- registerDetailsViewSection: inject driver role/status into tns-csi Pod pages
- registerDetailsViewHeaderAction: Benchmark shortcut on StorageClass detail
- registerAppBarAction: driver health badge (N/Nc M/Mn, color-coded)
- Trim sidebar from 6 → 4 entries (Overview, Snapshots, Metrics, Benchmark)

TrueNAS API integration:
- src/api/truenas.ts: ConfigStore-backed settings, WebSocket JSON-RPC client
  for pool.query (auth.login_with_api_key + pool.query)
- src/components/TnsCsiSettings.tsx: API key + server override settings UI
  with connection test button
- TnsCsiDataContext: fetch real pool stats (size/allocated/free/status)
- OverviewPage: three-tier pool capacity display (real data → error → metrics
  fallback)

Documentation:
- README, CHANGELOG, CONTRIBUTING, SECURITY
- docs/: architecture, deployment (Helm), getting-started, user-guide,
  troubleshooting

CI:
- .github/workflows/ci.yaml: lint + type-check + test on PR/push
- .github/workflows/release.yaml: workflow_dispatch versioned release

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
2026-02-18 16:37:56 -05:00

8.5 KiB
Raw Permalink Blame History

Security Policy

Overview

The Headlamp TNS-CSI Plugin is a visibility and benchmarking tool for the tns-csi Kubernetes CSI driver. Security considerations center on Kubernetes RBAC, network policies, and the limited write operations performed by the Benchmark page.

Security Model

Primarily Read-Only

The plugin is read-only for all pages except Benchmark:

  • No secrets access: The plugin does not read or store Kubernetes Secrets
  • No CRD installation: No custom resource definitions or cluster-level modifications
  • No PII: CSI resource metadata (names, namespaces, parameters) does not contain personally identifiable information
  • No external egress: All API calls go through the Kubernetes API server proxy; no external network calls

The Benchmark Exception

The Benchmark page creates and deletes a Kubernetes Job and PVC to run storage benchmarks. These resources are:

  • Labeled app.kubernetes.io/managed-by=headlamp-tns-csi-plugin for identification
  • Created only in the namespace the user explicitly selects
  • Automatically deleted when the benchmark completes or is stopped
  • Using the yasker/kbench:latest image (a public, well-known benchmark tool)

Grant benchmark write permissions only to users who should be able to initiate storage tests.

Data Flow

User Browser
    ↓ (HTTPS)
Headlamp Pod
    ↓ (in-cluster service account or user token)
Kubernetes API Server
    ↓ (list/watch StorageClasses, PVs, PVCs, pods, snapshots)
    ↓ (pod proxy: controller pod port 8080 → Prometheus metrics)
    ↓ (pod proxy: kbench pod → FIO log for benchmark results)
Plugin Frontend (React)

All communication uses Kubernetes authentication and authorization mechanisms. The plugin never stores credentials or bypasses RBAC.

RBAC Requirements

Minimal Read-Only Permissions

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: headlamp-tns-csi-reader
rules:
  - apiGroups: [""]
    resources: ["persistentvolumes", "pods"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses", "csidrivers"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["snapshot.storage.k8s.io"]
    resources: ["volumesnapshots", "volumesnapshotclasses"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["pods/log", "pods/proxy"]
    verbs: ["get"]
    # pods/proxy is used to fetch Prometheus metrics from the controller pod

Additional Permissions for Benchmark Page

  - apiGroups: ["batch"]
    resources: ["jobs"]
    verbs: ["get", "list", "watch", "create", "delete"]
  - apiGroups: [""]
    resources: ["persistentvolumeclaims"]
    verbs: ["create", "delete"]

Binding Example

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: headlamp-tns-csi
subjects:
  - kind: ServiceAccount
    name: headlamp
    namespace: kube-system   # adjust to your Headlamp namespace
roleRef:
  kind: ClusterRole
  name: headlamp-tns-csi-reader
  apiGroup: rbac.authorization.k8s.io

⚠️ Security Best Practices

  1. Principle of Least Privilege: Grant benchmark write permissions (jobs create/delete, persistentvolumeclaims create/delete) only to users who need them
  2. Namespace Scoping for Benchmarks: If possible, restrict benchmark Job/PVC permissions to a dedicated benchmark namespace using a namespaced Role rather than ClusterRole
  3. Pod Proxy Scoping: Scope pods/proxy access to kube-system only, or to pods matching the tns-csi controller label
  4. Audit Logging: Enable Kubernetes audit logging to track all API requests made through the plugin
  5. Image Pinning: Consider pinning yasker/kbench:latest to a specific digest in your environment for supply chain security

Network Security

Network Policies

If your cluster uses NetworkPolicies, ensure the Kubernetes API server can proxy requests to the tns-csi controller pod on port 8080:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-api-server-to-tns-csi-controller
  namespace: kube-system
spec:
  podSelector:
    matchLabels:
      app.kubernetes.io/name: tns-csi-driver
      app.kubernetes.io/component: controller
  policyTypes:
    - Ingress
  ingress:
    - ports:
        - protocol: TCP
          port: 8080

The Kubernetes API server performs the pod proxy hop, so policies should permit the API server (not Headlamp directly) to reach the controller pod.

TLS/HTTPS

  • External Access: Always access Headlamp over HTTPS
  • Internal Communication: Headlamp to API server uses the service account token over the cluster's internal network
  • Pod Proxy: API server → tns-csi controller happens over HTTP within the cluster (port 8080)

Authentication Methods

Service Account (Default)

Headlamp runs with a dedicated service account (headlamp in kube-system). All users share the same RBAC permissions.

Security Considerations:

  • All users have identical access to plugin functionality including Benchmark
  • Suitable for trusted internal environments
  • Simpler RBAC management

OIDC Token Authentication

Headlamp can use per-user OIDC tokens. RBAC is enforced per-user, enabling fine-grained access control:

  • Read-only users: bind only the reader ClusterRole
  • Benchmark users: bind the additional write permissions
  • Users without permissions see appropriate 403 errors

Vulnerability Reporting

Supported Versions

Security updates are applied to the latest release only.

Version Supported
latest
< latest

Reporting a Vulnerability

Report security vulnerabilities via:

  1. GitHub Security Advisories: Report a vulnerability
  2. GitHub Issues: Open an issue and mark it "security" if advisories are unavailable

Please do not open public GitHub issues for security vulnerabilities before a fix is available.

Response Timeline:

  • Acknowledgment: Within 48 hours
  • Initial Assessment: Within 1 week
  • Fix Timeline: Critical: 12 weeks; High: 24 weeks; Medium/Low: next release cycle

Dependency Security

The project uses:

  • npm audit: Runs automatically during npm install
  • GitHub Dependabot: Monitors dependencies and creates PRs for updates

Headlamp itself (@kinvolk/headlamp-plugin) is a peer dependency. Security updates to Headlamp should be applied by upgrading your Headlamp installation.

Minimum supported Headlamp version: v0.20.0

Deployment Security Checklist

Before deploying to production:

  • RBAC configured: ClusterRole and ClusterRoleBinding exist for Headlamp service account
  • Benchmark permissions scoped: Write permissions granted only to appropriate users/groups
  • Network policies: Allow API server → tns-csi controller traffic on port 8080
  • TLS enabled: Headlamp accessible only via HTTPS
  • Audit logging enabled: Kubernetes API audit logs capture requests
  • Plugin version: Running latest release
  • Dependencies audited: npm audit shows no critical vulnerabilities

Compliance

Data Residency

All data remains within your Kubernetes cluster. The plugin does not:

  • Send data to external services
  • Store data in browser localStorage (except any future settings)
  • Use third-party analytics or tracking

Audit Trail

All API requests are logged in Kubernetes API audit logs (if enabled). Pod proxy requests to the controller pod's metrics endpoint appear as:

{
  "verb": "get",
  "requestURI": "/api/v1/namespaces/kube-system/pods/<controller-pod>/proxy/metrics",
  "user": {
    "username": "system:serviceaccount:kube-system:headlamp"
  }
}

Privacy

The plugin processes only technical metadata (resource names, namespaces, CSI parameters, metrics values). No personal data is collected, stored, or transmitted.

Contact

License

This plugin is provided under the Apache-2.0 License. See LICENSE for details.