6c7064faf0
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
132 lines
5.6 KiB
Markdown
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 |
|