This repository has been archived on 2026-06-16. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
headlamp-polaris-plugin/docs/architecture/adr/005-annotation-exemption-management.md
T
2026-03-05 13:49:56 +00:00

132 lines
5.6 KiB
Markdown

# ADR-005: Annotation-Based Exemption Management
**Status:** Accepted
**Date:** 2026-03-05
**Deciders:** Plugin maintainers
## Context
Polaris allows exempting specific workloads from audit checks. When a workload is exempt, Polaris skips all audit checks for that resource. The exemption mechanism uses the annotation `polaris.fairwinds.com/exempt=true` on the workload resource.
The plugin needs to let users manage these exemptions directly from the Headlamp UI. Several approaches were considered:
1. Use Polaris's native annotation-based exemption mechanism
2. Create a separate exemption ConfigMap
3. Define a custom ExemptionPolicy CRD
4. Read-only display with kubectl instructions
**Constraints:**
- Polaris only recognizes `polaris.fairwinds.com/exempt` annotations on workload resources
- The plugin is otherwise read-only (this would be the only write operation)
- Users need appropriate RBAC permissions to patch workload resources
- Supported workload types: Deployments, StatefulSets, DaemonSets, Jobs, CronJobs
**Requirements:**
- Allow users to toggle exemptions for workloads from the Headlamp UI
- Use a mechanism that Polaris actually respects (exemptions must take effect on next scan)
- Support all workload types that Polaris audits
- Respect Kubernetes RBAC (only authorized users can manage exemptions)
## Decision
Use **Polaris's native annotation-based exemption mechanism**. The `ExemptionManager` component patches `polaris.fairwinds.com/exempt` annotations onto workload resources via `ApiProxy.request`.
**Implementation:**
- `ExemptionManager` component in `ExemptionManager.tsx` provides a toggle UI for each workload
- Exemptions are applied via `ApiProxy.request` with `method: 'PATCH'` and `Content-Type: application/strategic-merge-patch+json`
- Patch payload sets `metadata.annotations["polaris.fairwinds.com/exempt"]` to `"true"` or removes the annotation
- This is the only write operation in the entire plugin
- RBAC is enforced by Kubernetes - users without `patch` permission on the workload resource will receive a 403 error
## Consequences
### Positive
-**Uses Polaris's own exemption mechanism** - No custom storage or translation layer needed
-**Exemptions visible in standard kubectl output** - `kubectl get deployment -o yaml` shows the annotation
-**No additional CRDs or ConfigMaps** - No custom resources to manage or clean up
-**Polaris automatically respects annotations** - Exemptions take effect on the next audit scan
-**Standard Kubernetes pattern** - Annotations are the idiomatic way to attach metadata to resources
### Negative
-**Requires write RBAC on workload resources** - Users need `patch` permission on deployments, statefulsets, etc.
- **Mitigated by:** RBAC scoping - only users with patch permission can manage exemptions; UI shows clear error for 403
-**Annotation changes not versioned or auditable** - Beyond standard Kubernetes resource history
- **Mitigated by:** Kubernetes audit logging captures annotation patches; resource `metadata.managedFields` tracks changes
-**Only supports full-resource exemption** - Cannot exempt individual checks (Polaris limitation)
- **Mitigated by:** This matches Polaris's own annotation-level granularity
### Neutral
- Strategic merge patch is the standard Kubernetes patching strategy for adding/removing annotations
- The annotation key (`polaris.fairwinds.com/exempt`) is defined by Polaris and unlikely to change
- Exemption state is stored on the workload resource itself, so it moves with the resource if migrated
## Alternatives Considered
### Option 1: Separate Exemption ConfigMap
**Pros:**
- Centralizes all exemptions in one place
- Does not require write access to workload resources
- Easy to audit all exemptions at once
**Cons:**
- Polaris does not read exemptions from ConfigMaps - it only checks annotations
- Would require a custom reconciliation controller to sync ConfigMap entries to annotations
- Adds operational complexity
**Decision:** Rejected (Polaris does not support ConfigMap-based exemptions)
### Option 2: Custom ExemptionPolicy CRD
**Pros:**
- Dedicated resource type for exemption management
- Could support per-check exemptions, time-based exemptions, etc.
- Clean separation of concerns
**Cons:**
- Over-engineering for what is essentially an annotation toggle
- Would require a custom controller to reconcile CRDs to annotations
- Adds CRD installation as a prerequisite
- Polaris still needs the annotation, so the CRD would be an indirection layer
**Decision:** Rejected (over-engineering for annotation toggle, would require a controller)
### Option 3: Read-Only Display with kubectl Instructions
**Pros:**
- No write operations in the plugin
- No RBAC requirements beyond read access
- Simpler implementation
**Cons:**
- Poor user experience - users must switch to terminal to manage exemptions
- Defeats the purpose of a UI plugin
- Error-prone (users may mistype annotation keys)
**Decision:** Rejected (poor UX compared to in-UI toggle)
## References
- [Polaris Exemptions Documentation](https://polaris.docs.fairwinds.com/customization/exemptions/)
- [Kubernetes Annotations](https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/)
- [Strategic Merge Patch](https://kubernetes.io/docs/tasks/manage-kubernetes-resources/update-api-object-kubectl-patch/#use-a-strategic-merge-patch-to-update-a-deployment)
- [Plugin Implementation](../../../src/components/ExemptionManager.tsx)
## Revision History
| Date | Author | Change |
| ---------- | ----------- | ---------------- |
| 2026-03-05 | Plugin Team | Initial decision |