267 lines
6.4 KiB
Markdown
267 lines
6.4 KiB
Markdown
# Facet Quota Configuration Guide
|
|
|
|
> **Version**: 1.0.0
|
|
> **Sprint**: SPRINT_20260105_002_003_FACET
|
|
> **Last Updated**: 2026-01-07
|
|
|
|
This guide covers configuration and operation of per-facet drift quotas in StellaOps.
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
Facet quotas control how much change is acceptable in different parts of a container image between builds. When drift exceeds a quota, StellaOps can:
|
|
|
|
- **Warn**: Log and report the drift, continue processing
|
|
- **Block**: Fail the policy gate, prevent deployment
|
|
- **Auto-VEX**: Generate a VEX draft for human review
|
|
|
|
### What are Facets?
|
|
|
|
Facets are logical groupings of files in a container image:
|
|
|
|
| Facet | Description | Typical Files |
|
|
|-------|-------------|---------------|
|
|
| `binaries` | Executables and libraries | `*.so`, `*.dll`, ELF files |
|
|
| `lang-deps` | Language package dependencies | `node_modules/`, `site-packages/`, `.m2/` |
|
|
| `os-packages` | OS-level packages | RPM, DEB, APK metadata |
|
|
| `configs` | Configuration files | `*.conf`, `*.yaml`, `*.json` |
|
|
| `data` | Static data files | Images, fonts, templates |
|
|
|
|
### Why Per-Facet Quotas?
|
|
|
|
Different file types have different risk profiles:
|
|
|
|
- A single binary change might be intentional (rebuild) or might indicate compromise
|
|
- 100 new npm packages might be a normal dependency update
|
|
- Removing OS security packages is always suspicious
|
|
|
|
Per-facet quotas let you apply appropriate controls to each category.
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
### File Location
|
|
|
|
```
|
|
/etc/stellaops/facet-quotas.yaml
|
|
```
|
|
|
|
Or via environment variable:
|
|
```bash
|
|
STELLAOPS_FACET_QUOTAS_PATH=/path/to/facet-quotas.yaml
|
|
```
|
|
|
|
### Basic Structure
|
|
|
|
```yaml
|
|
# Default quota for all facets
|
|
defaults:
|
|
maxChurnPercent: 30 # Max % of files that can change
|
|
maxChangedFiles: 100 # Max absolute changed files
|
|
maxAddedFiles: 50 # Max new files
|
|
maxRemovedFiles: 50 # Max removed files
|
|
action: warn # warn | block | auto-vex
|
|
|
|
# Per-facet overrides
|
|
facets:
|
|
binaries:
|
|
maxChurnPercent: 10
|
|
action: block
|
|
lang-deps:
|
|
maxChurnPercent: 40
|
|
action: auto-vex
|
|
```
|
|
|
|
### Quota Parameters
|
|
|
|
| Parameter | Type | Description |
|
|
|-----------|------|-------------|
|
|
| `maxChurnPercent` | decimal | Maximum percentage of files in the facet that can change |
|
|
| `maxChangedFiles` | int | Maximum absolute number of changed files |
|
|
| `maxAddedFiles` | int | Maximum number of new files (optional) |
|
|
| `maxRemovedFiles` | int | Maximum number of removed files (optional) |
|
|
| `action` | string | Action when quota exceeded: `warn`, `block`, `auto-vex` |
|
|
| `allowlist` | list | Glob patterns to exclude from quota calculation |
|
|
|
|
### Using Profiles
|
|
|
|
StellaOps includes predefined quota profiles:
|
|
|
|
```yaml
|
|
# Use a predefined profile
|
|
profile: moderate # strict | moderate | permissive
|
|
|
|
# Optionally override specific facets
|
|
facets:
|
|
binaries:
|
|
action: block # Override from profile
|
|
```
|
|
|
|
| Profile | Description | Use Case |
|
|
|---------|-------------|----------|
|
|
| `strict` | Minimal tolerance, blocks most drift | Production, regulated |
|
|
| `moderate` | Balanced, auto-VEX for review | Staging, pre-prod |
|
|
| `permissive` | Relaxed, warnings only | Development |
|
|
|
|
---
|
|
|
|
## Policy Integration
|
|
|
|
### Enabling Quota Gates
|
|
|
|
In your policy configuration:
|
|
|
|
```yaml
|
|
# policy-gates.yaml
|
|
gates:
|
|
- name: facet-quota
|
|
enabled: true
|
|
options:
|
|
configPath: /etc/stellaops/facet-quotas.yaml
|
|
failOnMissingSeal: true # Fail if no baseline seal exists
|
|
```
|
|
|
|
### Seal Management
|
|
|
|
Quotas compare current state against a "sealed" baseline:
|
|
|
|
```bash
|
|
# Seal current image as baseline
|
|
stella facet seal --image myapp:v1.2.3 --tenant production
|
|
|
|
# List seals
|
|
stella facet seals list --tenant production
|
|
|
|
# Compare against seal
|
|
stella facet drift --image myapp:v1.2.4 --baseline v1.2.3
|
|
```
|
|
|
|
---
|
|
|
|
## Auto-VEX Workflow
|
|
|
|
When quota action is `auto-vex`, StellaOps:
|
|
|
|
1. Generates a VEX draft with drift justification
|
|
2. Queues the draft for human review
|
|
3. Sends notifications to configured channels
|
|
|
|
### VEX Draft Structure
|
|
|
|
```json
|
|
{
|
|
"statements": [{
|
|
"vulnerability": "FACET-DRIFT-2026-001234",
|
|
"status": "under_investigation",
|
|
"justification": "facet_drift_detected",
|
|
"impact_statement": "Drift in 'binaries' facet: 15% churn (quota: 10%), 12 files changed"
|
|
}]
|
|
}
|
|
```
|
|
|
|
### Approving VEX Drafts
|
|
|
|
```bash
|
|
# List pending drafts
|
|
stella vex drafts list --status pending
|
|
|
|
# Approve a draft
|
|
stella vex draft approve --id <draft-id> --reason "Expected rebuild"
|
|
|
|
# Reject a draft
|
|
stella vex draft reject --id <draft-id> --reason "Unexpected changes"
|
|
```
|
|
|
|
---
|
|
|
|
## Monitoring
|
|
|
|
### Metrics
|
|
|
|
| Metric | Description |
|
|
|--------|-------------|
|
|
| `facet_drift_evaluations_total` | Total drift evaluations |
|
|
| `facet_quota_exceeded_total` | Quota breaches by facet and action |
|
|
| `facet_vex_drafts_created_total` | Auto-VEX drafts generated |
|
|
| `facet_seal_operations_total` | Seal create/update operations |
|
|
|
|
### Grafana Dashboard
|
|
|
|
Import the facet quota dashboard:
|
|
```
|
|
devops/observability/grafana/facet-quota-metrics.json
|
|
```
|
|
|
|
### Alerts
|
|
|
|
Key alerts to configure:
|
|
|
|
- `FacetQuotaBlockRate`: High rate of blocked builds
|
|
- `FacetDriftAnomalous`: Unusual drift patterns
|
|
- `FacetVexDraftBacklog`: Growing VEX draft queue
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Quota Unexpectedly Blocking
|
|
|
|
1. Check current quota configuration:
|
|
```bash
|
|
stella facet quota show --facet binaries
|
|
```
|
|
|
|
2. Review drift details:
|
|
```bash
|
|
stella facet drift --image myapp:latest --verbose
|
|
```
|
|
|
|
3. Check allowlist patterns:
|
|
```bash
|
|
stella facet quota test-allowlist --pattern "**/__pycache__/**"
|
|
```
|
|
|
|
### Missing Baseline Seal
|
|
|
|
```bash
|
|
# Create initial seal
|
|
stella facet seal --image myapp:v1.0.0 --tenant production
|
|
|
|
# Or skip quota check for first build
|
|
stella scan --image myapp:v1.0.0 --skip-facet-quota
|
|
```
|
|
|
|
### VEX Draft Not Generated
|
|
|
|
1. Verify action is `auto-vex` not `warn`:
|
|
```yaml
|
|
facets:
|
|
binaries:
|
|
action: auto-vex # Not 'warn'
|
|
```
|
|
|
|
2. Check VEX emitter is enabled:
|
|
```bash
|
|
stella config get excititor.vex.facetDriftEnabled
|
|
```
|
|
|
|
---
|
|
|
|
## Best Practices
|
|
|
|
1. **Start with `moderate` profile** in staging, tune based on observations
|
|
2. **Use `strict` for production** with explicit allowlists
|
|
3. **Review auto-VEX drafts daily** to prevent backlog
|
|
4. **Seal after each release** to establish new baseline
|
|
5. **Monitor quota metrics** to detect configuration drift
|
|
|
|
---
|
|
|
|
## Revision History
|
|
|
|
| Version | Date | Author | Changes |
|
|
|---------|------|--------|---------|
|
|
| 1.0.0 | 2026-01-07 | Agent | Initial release |
|