audit work, fixed StellaOps.sln warnings/errors, fixed tests, sprints work, new advisories

This commit is contained in:
master
2026-01-07 18:49:59 +02:00
parent 04ec098046
commit 608a7f85c0
866 changed files with 56323 additions and 6231 deletions

View File

@@ -0,0 +1,242 @@
# Facet Seal Admission Webhook Configuration
**Sprint:** SPRINT_20260105_002_004_CLI
**Task:** CLI-017 - Admission webhook configuration documentation
## Overview
The StellaOps Zastava admission webhook validates facet seals during Kubernetes pod admission. When enabled, it ensures that container images have valid facet seals and that any drift from the baseline is within acceptable quotas.
## Prerequisites
- Kubernetes cluster with admission webhook support
- StellaOps Zastava webhook deployed
- Certificate management for webhook TLS
- Network access from API server to webhook endpoint
## Enabling Facet Validation
Facet seal validation is opt-in per namespace using annotations.
### Namespace Annotation
Add the following annotation to enable facet validation:
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: production
annotations:
stellaops.io/facet-seal-required: "true"
```
### Annotation Values
| Value | Behavior |
|-------|----------|
| `"true"` | Facet seal validation enabled |
| `"false"` | Facet seal validation disabled |
| (not set) | Facet seal validation disabled |
## Validation Behavior
When facet validation is enabled, the webhook performs these checks:
1. **Seal Lookup**: Load the facet seal for the image digest
2. **Signature Verification**: Verify the seal's DSSE signature (if present)
3. **Drift Computation**: Compare current image state against baseline seal
4. **Quota Evaluation**: Check drift against configured quotas
### Verdict Outcomes
| Verdict | Result | Description |
|---------|--------|-------------|
| `Ok` | Allow | Drift within quotas |
| `Warning` | Allow (with warning) | Approaching quota limits |
| `Blocked` | Deny | Quota exceeded |
| `RequiresVex` | Deny | Requires VEX authorization |
## Configuration Options
### Webhook Deployment
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: zastava-webhook
namespace: stellaops-system
spec:
replicas: 3
selector:
matchLabels:
app: zastava-webhook
template:
metadata:
labels:
app: zastava-webhook
spec:
containers:
- name: webhook
image: stellaops/zastava-webhook:latest
ports:
- containerPort: 8443
env:
- name: STELLAOPS_BACKEND_URL
value: "https://api.stellaops.internal"
- name: STELLAOPS_FACET_SEAL_STORE
value: "remote"
volumeMounts:
- name: webhook-certs
mountPath: /etc/webhook/certs
readOnly: true
volumes:
- name: webhook-certs
secret:
secretName: zastava-webhook-certs
```
### ValidatingWebhookConfiguration
```yaml
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: stellaops-facet-admission
webhooks:
- name: facet.admission.stellaops.io
clientConfig:
service:
name: zastava-webhook
namespace: stellaops-system
path: /validate
caBundle: ${CA_BUNDLE}
rules:
- operations: ["CREATE", "UPDATE"]
apiGroups: [""]
apiVersions: ["v1"]
resources: ["pods"]
namespaceSelector:
matchExpressions:
- key: stellaops.io/facet-seal-required
operator: In
values: ["true"]
failurePolicy: Fail
sideEffects: None
admissionReviewVersions: ["v1"]
```
## Quota Configuration
Facet drift quotas can be configured per namespace or globally.
### Global Quotas (ConfigMap)
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: stellaops-facet-quotas
namespace: stellaops-system
data:
default.yaml: |
quotas:
runtime:
warningThreshold: 10
blockThreshold: 25
vexThreshold: 50
config:
warningThreshold: 20
blockThreshold: 40
vexThreshold: 60
static:
warningThreshold: 30
blockThreshold: 50
vexThreshold: 75
```
### Per-Namespace Overrides
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: staging
annotations:
stellaops.io/facet-seal-required: "true"
stellaops.io/facet-quota-runtime-warn: "20"
stellaops.io/facet-quota-runtime-block: "50"
```
## Troubleshooting
### Common Issues
#### Seal Not Found
```
Admission denied: facet.seal.missing
No facet seal found for image sha256:abc123...
```
**Resolution**: Ensure the image was sealed before deployment:
```bash
stella seal sha256:abc123 --store
```
#### Invalid Signature
```
Admission denied: facet.seal.invalid_signature
Facet seal signature verification failed
```
**Resolution**: Verify the seal was signed with a trusted key and the trust roots are configured.
#### Quota Exceeded
```
Admission denied: facet.quota.exceeded
Facet quota exceeded: runtime(45.2%)
```
**Resolution**: Either:
1. Re-seal the image with current state
2. Generate and approve a VEX authorization
3. Adjust quota thresholds
### Debugging
Enable verbose logging:
```yaml
env:
- name: STELLAOPS_LOG_LEVEL
value: "Debug"
```
View webhook logs:
```bash
kubectl logs -n stellaops-system -l app=zastava-webhook
```
## Metrics
The webhook exposes Prometheus metrics:
| Metric | Type | Description |
|--------|------|-------------|
| `stellaops_facet_admission_total` | Counter | Total admission requests |
| `stellaops_facet_admission_allowed` | Counter | Allowed admissions |
| `stellaops_facet_admission_denied` | Counter | Denied admissions |
| `stellaops_facet_drift_percent` | Histogram | Drift percentage distribution |
| `stellaops_facet_validation_duration_seconds` | Histogram | Validation latency |
## Related Documentation
- [stella seal Command](../commands/seal.md)
- [stella vex gen --from-drift](../commands/vex.md#stella-vex-gen---from-drift)
- [Facet Drift Analysis](../commands/facet-drift.md)

View File

@@ -0,0 +1,267 @@
# stella drift (Facet Analysis) - Command Guide
**Sprint:** SPRINT_20260105_002_004_CLI
**Task:** CLI-016 - Facet drift command documentation
## Overview
The `stella drift` command analyzes facet drift between a baseline seal and the current state of a container image. Unlike reachability drift (which tracks call paths to vulnerable code), facet drift tracks file-level changes within categorized image layers.
## Commands
### stella drift
Analyze facet drift for an image against a baseline seal.
```bash
stella drift <IMAGE> [OPTIONS]
```
#### Arguments
| Argument | Description |
|----------|-------------|
| `IMAGE` | Image reference or digest to analyze (required) |
#### Options
| Option | Alias | Description | Default |
|--------|-------|-------------|---------|
| `--baseline <ID>` | `-b` | Baseline seal ID for comparison | latest seal |
| `--format <FMT>` | `-f` | Output format: `table`, `json`, `yaml` | `table` |
| `--verbose` | `-v` | Show detailed file changes | `false` |
| `--fail-on-breach` | | Exit with error code if quota breached | `false` |
#### Examples
##### Basic drift analysis
```bash
stella drift sha256:abc123def456...
```
##### With specific baseline
```bash
stella drift myregistry.io/app:v2.0 --baseline seal-xyz789
```
##### JSON output for CI integration
```bash
stella drift sha256:abc123 --format json > drift-report.json
```
##### Fail build on quota breach
```bash
stella drift sha256:abc123 --fail-on-breach
```
##### Verbose output with file details
```bash
stella drift sha256:abc123 --verbose
```
---
## Output Formats
### Table Format (Default)
```
Overall Verdict: Warning
Total Changed Files: 15
+----------+-------+---------+----------+---------+-----------+
| Facet | Added | Removed | Modified | Churn % | Verdict |
+----------+-------+---------+----------+---------+-----------+
| runtime | 2 | 1 | 3 | 12.5% | Warning |
| config | 5 | 0 | 2 | 8.2% | Ok |
| static | 0 | 2 | 0 | 3.1% | Ok |
+----------+-------+---------+----------+---------+-----------+
```
With `--verbose`:
```
File Changes:
runtime
+ /usr/lib/libcrypto.so.3.0.1
+ /usr/lib/libssl.so.3.0.1
- /usr/lib/libcrypto.so.3.0.0
~ /usr/bin/app (sha256:old -> sha256:new)
~ /etc/app/config.yaml
~ /var/lib/app/data.db
```
### JSON Format
```json
{
"imageDigest": "sha256:abc123...",
"baselineSealId": "seal-xyz789",
"analyzedAt": "2026-01-05T10:30:00Z",
"overallVerdict": "warning",
"totalChangedFiles": 15,
"facetDrifts": [
{
"facetId": "runtime",
"baselineFileCount": 48,
"added": [
{
"path": "/usr/lib/libcrypto.so.3.0.1",
"digest": "sha256:new...",
"sizeBytes": 3145728,
"modifiedAt": null
}
],
"removed": [
{
"path": "/usr/lib/libcrypto.so.3.0.0",
"digest": "sha256:old...",
"sizeBytes": 3145600,
"modifiedAt": null
}
],
"modified": [
{
"path": "/usr/bin/app",
"previousDigest": "sha256:prev...",
"currentDigest": "sha256:curr...",
"previousSizeBytes": 15728640,
"currentSizeBytes": 15730000
}
],
"driftScore": 25.5,
"churnPercent": 12.5,
"quotaVerdict": "warning"
}
]
}
```
### YAML Format
```yaml
imageDigest: sha256:abc123...
baselineSealId: seal-xyz789
overallVerdict: warning
totalChangedFiles: 15
facetDrifts:
- facetId: runtime
added: 2
removed: 1
modified: 3
churnPercent: 12.50
verdict: warning
- facetId: config
added: 5
removed: 0
modified: 2
churnPercent: 8.20
verdict: ok
```
---
## Quota Verdicts
| Verdict | Description | Exit Code |
|---------|-------------|-----------|
| `Ok` | Drift within acceptable limits | 0 |
| `Warning` | Approaching quota limits | 0 |
| `Blocked` | Quota exceeded, deployment should be blocked | 2 |
| `RequiresVex` | Significant drift, requires VEX authorization | 2 |
## Exit Codes
| Code | Description |
|------|-------------|
| `0` | Success (no breach, or breach without `--fail-on-breach`) |
| `1` | Error (no baseline seal, image not found, etc.) |
| `2` | Quota breached (with `--fail-on-breach`) |
---
## CI/CD Integration
### GitHub Actions
```yaml
- name: Check Facet Drift
run: |
stella drift ${{ env.IMAGE_DIGEST }} \
--format json \
--fail-on-breach > drift.json
continue-on-error: true
id: drift-check
- name: Upload Drift Report
uses: actions/upload-artifact@v4
with:
name: facet-drift-report
path: drift.json
- name: Generate VEX if needed
if: failure() && steps.drift-check.outcome == 'failure'
run: |
stella vex gen --from-drift \
--image ${{ env.IMAGE_DIGEST }} \
--output vex-request.json
```
### GitLab CI
```yaml
facet-drift-check:
script:
- stella drift $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --fail-on-breach --format json > drift.json
artifacts:
paths:
- drift.json
reports:
codequality: drift.json
allow_failure: true
```
---
## Workflow: Handling Drift Breaches
When drift exceeds quotas:
1. **Review the drift report**
```bash
stella drift sha256:abc123 --verbose
```
2. **Determine if changes are intentional**
- Legitimate updates: Generate VEX authorization
- Unexpected changes: Investigate and remediate
3. **For intentional changes, generate VEX**
```bash
stella vex gen --from-drift --image sha256:abc123 --output vex.json
```
4. **Review and sign the VEX**
```bash
stella vex sign --input vex.json --key /path/to/key
```
5. **Or re-seal to establish new baseline**
```bash
stella seal sha256:abc123 --store
```
---
## Related Documentation
- [Facet Seal Command](./seal.md)
- [VEX Generation from Drift](./vex.md#stella-vex-gen---from-drift)
- [Reachability Drift (different concept)](./drift.md)
- [Admission Webhook Configuration](../admin/admission-webhook.md)

View File

@@ -0,0 +1,204 @@
# stella seal - Command Guide
**Sprint:** SPRINT_20260105_002_004_CLI
**Task:** CLI-016 - Facet seal command documentation
## Overview
The `stella seal` command creates cryptographic seals for container image facets. A facet seal captures the state of specific file categories (binaries, libraries, configs, etc.) within an image and produces Merkle roots for tamper detection and drift analysis.
## Commands
### stella seal
Create a facet seal for an image.
```bash
stella seal <IMAGE> [OPTIONS]
```
#### Arguments
| Argument | Description |
|----------|-------------|
| `IMAGE` | Image reference or digest to seal (required) |
#### Options
| Option | Alias | Description | Default |
|--------|-------|-------------|---------|
| `--output <PATH>` | `-o` | Output file path for seal | stdout |
| `--store` | `-s` | Store seal in remote API | `true` |
| `--sign` | | Sign seal with DSSE | `true` |
| `--key <PATH>` | `-k` | Private key path for signing | configured key |
| `--facets <LIST>` | `-f` | Specific facets to seal (comma-separated) | all |
| `--format <FMT>` | | Output format: `json`, `yaml`, `compact` | `json` |
| `--verbose` | `-v` | Enable verbose output | `false` |
#### Examples
##### Seal all facets
```bash
stella seal sha256:abc123def456...
```
##### Seal specific facets
```bash
stella seal myregistry.io/app:v1.0 --facets runtime,config
```
##### Output to file
```bash
stella seal myregistry.io/app:v1.0 --output seal.json
```
##### Seal without storing remotely
```bash
stella seal sha256:abc123 --no-store --output local-seal.json
```
##### Seal with custom signing key
```bash
stella seal sha256:abc123 --key /path/to/private.key
```
---
## Built-in Facets
| Facet ID | Name | Description | File Patterns |
|----------|------|-------------|---------------|
| `runtime` | Runtime Binaries | Executable binaries and shared libraries | `*.so`, `*.dll`, `/usr/bin/*` |
| `config` | Configuration | Configuration files | `*.conf`, `*.yaml`, `*.json`, `/etc/*` |
| `static` | Static Assets | Static web assets | `*.css`, `*.js`, `*.html` |
| `scripts` | Scripts | Script files | `*.sh`, `*.py`, `*.rb` |
| `data` | Data Files | Data and cache files | `*.db`, `*.sqlite`, `/var/lib/*` |
---
## Output Formats
### JSON Format (Default)
```json
{
"imageDigest": "sha256:abc123...",
"createdAt": "2026-01-05T10:30:00Z",
"combinedMerkleRoot": "sha256:combined...",
"facets": [
{
"facetId": "runtime",
"name": "Runtime Binaries",
"merkleRoot": "sha256:facet...",
"fileCount": 42,
"totalBytes": 15728640
}
],
"signature": {
"payloadType": "application/vnd.stellaops.facetseal+json",
"signatures": [...]
}
}
```
### YAML Format
```yaml
imageDigest: sha256:abc123...
createdAt: 2026-01-05T10:30:00Z
combinedMerkleRoot: sha256:combined...
facets:
- facetId: runtime
merkleRoot: sha256:facet...
fileCount: 42
```
### Compact Format
Single-line format for scripting:
```
sha256:abc123...|sha256:combined...|5
```
Format: `imageDigest|combinedRoot|facetCount`
---
## Exit Codes
| Code | Description |
|------|-------------|
| `0` | Success |
| `1` | General error |
| `2` | Image resolution failed |
| `3` | Signing failed |
| `4` | Storage failed |
---
## Environment Variables
| Variable | Description |
|----------|-------------|
| `STELLAOPS_BACKEND_URL` | Backend API URL for seal storage |
| `STELLAOPS_SIGNING_KEY` | Default signing key path |
| `STELLAOPS_TRUST_ROOTS` | Trust roots for verification |
---
## CI/CD Integration
### GitHub Actions
```yaml
- name: Seal Container Image
run: |
stella seal ${{ env.IMAGE_DIGEST }} \
--output seal.json \
--store
- name: Upload Seal Artifact
uses: actions/upload-artifact@v4
with:
name: facet-seal
path: seal.json
```
### GitLab CI
```yaml
seal-image:
script:
- stella seal $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --output seal.json
artifacts:
paths:
- seal.json
```
---
## Admission Integration
When Kubernetes admission is configured with facet seal validation, the webhook will:
1. Check if namespace has `stellaops.io/facet-seal-required=true` annotation
2. Load the seal for the image being deployed
3. Verify the seal signature
4. Compute drift against current image state
5. Admit/reject based on quota verdicts
See [Admission Webhook Configuration](../admin/admission-webhook.md) for setup details.
---
## Related Documentation
- [Facet Drift Analysis](./facet-drift.md)
- [VEX Generation from Drift](./vex.md#stella-vex-gen---from-drift)
- [Admission Webhook](../admin/admission-webhook.md)

View File

@@ -1,9 +1,11 @@
# stella vex Command Guide
# stella vex - Command Guide
## Commands
- `stella vex consensus --query <filter> [--output json|ndjson|table] [--offline]`
- `stella vex get --id <consensusId> [--offline]`
- `stella vex simulate --input <vexDocs> --policy <policyConfig> [--offline]`
- `stella vex gen --from-drift --image <IMAGE> [--baseline <SEAL_ID>] [--output <PATH>]`
## Flags (common)
- `--offline`: use cached consensus snapshots; fail with exit code 5 if remote would be hit.
@@ -21,3 +23,126 @@
## Offline/air-gap notes
- Cached snapshots are required when `--offline`; otherwise exit code 5 with remediation message.
- Trust roots for signature verification are loaded from `STELLA_TRUST_ROOTS` when verifying cached snapshots.
---
## stella vex gen --from-drift
**Sprint:** SPRINT_20260105_002_004_CLI
Generate VEX statements from facet drift analysis. This command analyzes drift between a baseline seal and the current image state, then generates OpenVEX documents for facets that require authorization.
### Usage
```bash
stella vex gen --from-drift --image <IMAGE> [OPTIONS]
```
### Required Options
| Option | Alias | Description |
|--------|-------|-------------|
| `--from-drift` | | Enable drift-based VEX generation |
| `--image <REF>` | `-i` | Image reference or digest to analyze |
### Optional Options
| Option | Alias | Description | Default |
|--------|-------|-------------|---------|
| `--baseline <ID>` | `-b` | Baseline seal ID for comparison | latest seal |
| `--output <PATH>` | `-o` | Output file path | stdout |
| `--format <FMT>` | `-f` | VEX format: `openvex`, `csaf` | `openvex` |
| `--status <STATUS>` | `-s` | VEX status: `under_investigation`, `not_affected`, `affected` | `under_investigation` |
| `--verbose` | `-v` | Enable verbose output | `false` |
### Examples
#### Generate VEX from drift
```bash
stella vex gen --from-drift --image sha256:abc123
```
#### Specify baseline seal
```bash
stella vex gen --from-drift --image myregistry.io/app:v2.0 --baseline seal-xyz789
```
#### Output to file with specific status
```bash
stella vex gen --from-drift --image sha256:abc123 \
--output vex-authorization.json \
--status not_affected
```
### Output Format (OpenVEX)
```json
{
"@context": "https://openvex.dev/ns",
"@id": "https://stellaops.io/vex/abc123-def456",
"author": "StellaOps CLI",
"timestamp": "2026-01-05T10:30:00Z",
"version": 1,
"statements": [
{
"@id": "vex:statement-1",
"status": "under_investigation",
"timestamp": "2026-01-05T10:30:00Z",
"products": [
{
"@id": "sha256:abc123...",
"identifiers": {
"facet": "runtime"
}
}
],
"justification": "Facet drift authorization for runtime. Churn: 15.50% (3 added, 1 removed, 2 modified)",
"action_statement": "Review required before deployment"
}
]
}
```
### Exit Codes
| Code | Description |
|------|-------------|
| `0` | Success |
| `1` | Error or no baseline seal found |
| `2` | Image resolution failed |
### Workflow Integration
The `vex gen --from-drift` command is typically used in a deployment pipeline:
1. **Build**: Container image is built
2. **Seal**: `stella seal` creates baseline seal at build time
3. **Deploy**: Deployment triggers admission webhook
4. **Drift Detection**: If drift exceeds quota, deployment is blocked
5. **VEX Generation**: `stella vex gen --from-drift` creates authorization document
6. **Review**: Security team reviews and signs VEX
7. **Retry Deploy**: With VEX in place, deployment proceeds
```bash
# After deployment blocked due to drift
stella vex gen --from-drift --image $IMAGE_DIGEST \
--output vex-authorization.json
# Review and sign the VEX document
stella vex sign --input vex-authorization.json --key $SIGNING_KEY
# Ingest the signed VEX
stella vex ingest --input vex-authorization.signed.json
# Retry deployment (webhook will now accept)
kubectl apply -f deployment.yaml
```
### Related Documentation
- [Facet Seal Command](./seal.md)
- [Facet Drift Analysis](./facet-drift.md)
- [Admission Webhook Configuration](../admin/admission-webhook.md)