audit work, fixed StellaOps.sln warnings/errors, fixed tests, sprints work, new advisories
This commit is contained in:
242
docs/modules/cli/guides/admin/admission-webhook.md
Normal file
242
docs/modules/cli/guides/admin/admission-webhook.md
Normal 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)
|
||||
267
docs/modules/cli/guides/commands/facet-drift.md
Normal file
267
docs/modules/cli/guides/commands/facet-drift.md
Normal 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)
|
||||
204
docs/modules/cli/guides/commands/seal.md
Normal file
204
docs/modules/cli/guides/commands/seal.md
Normal 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)
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user