fix tests. new product advisories enhancements
This commit is contained in:
35
docs/contracts/sigstore-services.example.json
Normal file
35
docs/contracts/sigstore-services.example.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"version": 1,
|
||||
"rekor": {
|
||||
"url": "https://rekor.sigstore.dev",
|
||||
"tile_base_url": "https://rekor.sigstore.dev/tile/",
|
||||
"log_id": "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d",
|
||||
"public_key_target": "rekor-key-v1"
|
||||
},
|
||||
"fulcio": {
|
||||
"url": "https://fulcio.sigstore.dev",
|
||||
"root_cert_target": "fulcio-root-2026Q1"
|
||||
},
|
||||
"ct_log": {
|
||||
"url": "https://ctfe.sigstore.dev",
|
||||
"public_key_target": "ctfe-key-v1"
|
||||
},
|
||||
"timestamp_authority": {
|
||||
"url": "https://tsa.sigstore.dev",
|
||||
"cert_chain_target": "tsa-chain-2026Q1"
|
||||
},
|
||||
"overrides": {
|
||||
"staging": {
|
||||
"rekor_url": "https://rekor.sigstage.dev",
|
||||
"fulcio_url": "https://fulcio.sigstage.dev"
|
||||
},
|
||||
"airgap": {
|
||||
"rekor_url": "https://rekor.internal:8080",
|
||||
"fulcio_url": "https://fulcio.internal:8081"
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"updated_at": "2026-01-25T00:00:00Z",
|
||||
"note": "Production Sigstore endpoints - January 2026"
|
||||
}
|
||||
}
|
||||
122
docs/contracts/sigstore-services.schema.json
Normal file
122
docs/contracts/sigstore-services.schema.json
Normal file
@@ -0,0 +1,122 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://stella-ops.org/schemas/sigstore-services/v1",
|
||||
"title": "Sigstore Services Map",
|
||||
"description": "Service discovery map for Sigstore infrastructure endpoints. Distributed via TUF for dynamic endpoint management without client reconfiguration.",
|
||||
"type": "object",
|
||||
"required": ["version", "rekor"],
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "Schema version for forward compatibility"
|
||||
},
|
||||
"rekor": {
|
||||
"type": "object",
|
||||
"description": "Rekor transparency log configuration",
|
||||
"required": ["url"],
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"description": "Primary Rekor API endpoint"
|
||||
},
|
||||
"tile_base_url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"description": "Optional tile endpoint (defaults to {url}/tile/)"
|
||||
},
|
||||
"log_id": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-f0-9]{64}$",
|
||||
"description": "SHA-256 hash of log public key (hex-encoded)"
|
||||
},
|
||||
"public_key_target": {
|
||||
"type": "string",
|
||||
"description": "TUF target name for Rekor public key"
|
||||
}
|
||||
}
|
||||
},
|
||||
"fulcio": {
|
||||
"type": "object",
|
||||
"description": "Fulcio certificate authority configuration",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"description": "Fulcio API endpoint"
|
||||
},
|
||||
"root_cert_target": {
|
||||
"type": "string",
|
||||
"description": "TUF target name for Fulcio root certificate"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ct_log": {
|
||||
"type": "object",
|
||||
"description": "Certificate Transparency log configuration",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"description": "CT log API endpoint"
|
||||
},
|
||||
"public_key_target": {
|
||||
"type": "string",
|
||||
"description": "TUF target name for CT log public key"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp_authority": {
|
||||
"type": "object",
|
||||
"description": "Timestamp authority configuration",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"format": "uri",
|
||||
"description": "TSA endpoint"
|
||||
},
|
||||
"cert_chain_target": {
|
||||
"type": "string",
|
||||
"description": "TUF target name for TSA certificate chain"
|
||||
}
|
||||
}
|
||||
},
|
||||
"overrides": {
|
||||
"type": "object",
|
||||
"description": "Site-local endpoint overrides by environment",
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"rekor_url": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"fulcio_url": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
},
|
||||
"ct_log_url": {
|
||||
"type": "string",
|
||||
"format": "uri"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"description": "Additional metadata",
|
||||
"properties": {
|
||||
"updated_at": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Last update timestamp"
|
||||
},
|
||||
"note": {
|
||||
"type": "string",
|
||||
"description": "Human-readable note about this configuration"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
73
docs/events/attestor.logged@1.json
Normal file
73
docs/events/attestor.logged@1.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://docs.stella-ops.org/events/attestor.logged@1.json",
|
||||
"title": "Attestor Logged Event",
|
||||
"description": "Emitted when an attestation is logged to a transparency log",
|
||||
"type": "object",
|
||||
"required": ["eventId", "kind", "version", "tenant", "ts", "payload"],
|
||||
"properties": {
|
||||
"eventId": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Unique event identifier"
|
||||
},
|
||||
"kind": {
|
||||
"const": "attestor.logged",
|
||||
"description": "Event kind"
|
||||
},
|
||||
"version": {
|
||||
"const": "1",
|
||||
"description": "Schema version"
|
||||
},
|
||||
"tenant": {
|
||||
"type": "string",
|
||||
"description": "Tenant identifier"
|
||||
},
|
||||
"ts": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Event timestamp in ISO 8601 format"
|
||||
},
|
||||
"actor": {
|
||||
"type": "string",
|
||||
"description": "Service or user that triggered the event"
|
||||
},
|
||||
"payload": {
|
||||
"type": "object",
|
||||
"required": ["attestationId", "imageDigest", "imageName"],
|
||||
"properties": {
|
||||
"attestationId": {
|
||||
"type": "string",
|
||||
"description": "Unique attestation identifier"
|
||||
},
|
||||
"imageDigest": {
|
||||
"type": "string",
|
||||
"description": "Image digest (sha256)"
|
||||
},
|
||||
"imageName": {
|
||||
"type": "string",
|
||||
"description": "Full image name with tag"
|
||||
},
|
||||
"predicateType": {
|
||||
"type": "string",
|
||||
"description": "In-toto predicate type URI"
|
||||
},
|
||||
"logIndex": {
|
||||
"type": "integer",
|
||||
"description": "Transparency log index"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"attestation": { "type": "string", "format": "uri" },
|
||||
"rekor": { "type": "string", "format": "uri" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"type": "object",
|
||||
"additionalProperties": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
78
docs/events/scanner.report.ready@1.json
Normal file
78
docs/events/scanner.report.ready@1.json
Normal file
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://docs.stella-ops.org/events/scanner.report.ready@1.json",
|
||||
"title": "Scanner Report Ready Event",
|
||||
"description": "Emitted when a scan report is generated and ready for download",
|
||||
"type": "object",
|
||||
"required": ["eventId", "kind", "version", "tenant", "ts", "payload"],
|
||||
"properties": {
|
||||
"eventId": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Unique event identifier"
|
||||
},
|
||||
"kind": {
|
||||
"const": "scanner.report.ready",
|
||||
"description": "Event kind"
|
||||
},
|
||||
"version": {
|
||||
"const": "1",
|
||||
"description": "Schema version"
|
||||
},
|
||||
"tenant": {
|
||||
"type": "string",
|
||||
"description": "Tenant identifier"
|
||||
},
|
||||
"ts": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Event timestamp in ISO 8601 format"
|
||||
},
|
||||
"actor": {
|
||||
"type": "string",
|
||||
"description": "Service or user that triggered the event"
|
||||
},
|
||||
"payload": {
|
||||
"type": "object",
|
||||
"required": ["reportId", "scanId", "imageDigest", "imageName"],
|
||||
"properties": {
|
||||
"reportId": {
|
||||
"type": "string",
|
||||
"description": "Unique report identifier"
|
||||
},
|
||||
"scanId": {
|
||||
"type": "string",
|
||||
"description": "Related scan identifier"
|
||||
},
|
||||
"imageDigest": {
|
||||
"type": "string",
|
||||
"description": "Image digest (sha256)"
|
||||
},
|
||||
"imageName": {
|
||||
"type": "string",
|
||||
"description": "Full image name with tag"
|
||||
},
|
||||
"format": {
|
||||
"type": "string",
|
||||
"enum": ["cyclonedx", "spdx", "sarif"],
|
||||
"description": "Report format"
|
||||
},
|
||||
"size": {
|
||||
"type": "integer",
|
||||
"description": "Report size in bytes"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"report": { "type": "string", "format": "uri" },
|
||||
"download": { "type": "string", "format": "uri" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"type": "object",
|
||||
"additionalProperties": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
87
docs/events/scanner.scan.completed@1.json
Normal file
87
docs/events/scanner.scan.completed@1.json
Normal file
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://docs.stella-ops.org/events/scanner.scan.completed@1.json",
|
||||
"title": "Scanner Scan Completed Event",
|
||||
"description": "Emitted when a container image scan completes",
|
||||
"type": "object",
|
||||
"required": ["eventId", "kind", "version", "tenant", "ts", "payload"],
|
||||
"properties": {
|
||||
"eventId": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Unique event identifier"
|
||||
},
|
||||
"kind": {
|
||||
"const": "scanner.scan.completed",
|
||||
"description": "Event kind"
|
||||
},
|
||||
"version": {
|
||||
"const": "1",
|
||||
"description": "Schema version"
|
||||
},
|
||||
"tenant": {
|
||||
"type": "string",
|
||||
"description": "Tenant identifier"
|
||||
},
|
||||
"ts": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Event timestamp in ISO 8601 format"
|
||||
},
|
||||
"actor": {
|
||||
"type": "string",
|
||||
"description": "Service or user that triggered the event"
|
||||
},
|
||||
"payload": {
|
||||
"type": "object",
|
||||
"required": ["scanId", "imageDigest", "imageName", "verdict"],
|
||||
"properties": {
|
||||
"scanId": {
|
||||
"type": "string",
|
||||
"description": "Unique scan identifier"
|
||||
},
|
||||
"imageDigest": {
|
||||
"type": "string",
|
||||
"description": "Image digest (sha256)"
|
||||
},
|
||||
"imageName": {
|
||||
"type": "string",
|
||||
"description": "Full image name with tag"
|
||||
},
|
||||
"verdict": {
|
||||
"type": "string",
|
||||
"enum": ["pass", "fail"],
|
||||
"description": "Scan verdict"
|
||||
},
|
||||
"findingsCount": {
|
||||
"type": "integer",
|
||||
"description": "Total number of findings"
|
||||
},
|
||||
"vulnerabilities": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"critical": { "type": "integer" },
|
||||
"high": { "type": "integer" },
|
||||
"medium": { "type": "integer" },
|
||||
"low": { "type": "integer" }
|
||||
}
|
||||
},
|
||||
"scanDurationMs": {
|
||||
"type": "integer",
|
||||
"description": "Scan duration in milliseconds"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"findings": { "type": "string", "format": "uri" },
|
||||
"sbom": { "type": "string", "format": "uri" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"type": "object",
|
||||
"additionalProperties": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
73
docs/events/scheduler.rescan.delta@1.json
Normal file
73
docs/events/scheduler.rescan.delta@1.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://docs.stella-ops.org/events/scheduler.rescan.delta@1.json",
|
||||
"title": "Scheduler Rescan Delta Event",
|
||||
"description": "Emitted when a scheduled rescan detects vulnerability changes",
|
||||
"type": "object",
|
||||
"required": ["eventId", "kind", "version", "tenant", "ts", "payload"],
|
||||
"properties": {
|
||||
"eventId": {
|
||||
"type": "string",
|
||||
"format": "uuid",
|
||||
"description": "Unique event identifier"
|
||||
},
|
||||
"kind": {
|
||||
"const": "scheduler.rescan.delta",
|
||||
"description": "Event kind"
|
||||
},
|
||||
"version": {
|
||||
"const": "1",
|
||||
"description": "Schema version"
|
||||
},
|
||||
"tenant": {
|
||||
"type": "string",
|
||||
"description": "Tenant identifier"
|
||||
},
|
||||
"ts": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "Event timestamp in ISO 8601 format"
|
||||
},
|
||||
"actor": {
|
||||
"type": "string",
|
||||
"description": "Service or user that triggered the event"
|
||||
},
|
||||
"payload": {
|
||||
"type": "object",
|
||||
"required": ["scheduleId", "deltaId"],
|
||||
"properties": {
|
||||
"scheduleId": {
|
||||
"type": "string",
|
||||
"description": "Schedule identifier"
|
||||
},
|
||||
"deltaId": {
|
||||
"type": "string",
|
||||
"description": "Delta report identifier"
|
||||
},
|
||||
"imagesAffected": {
|
||||
"type": "integer",
|
||||
"description": "Number of images affected"
|
||||
},
|
||||
"newVulnerabilities": {
|
||||
"type": "integer",
|
||||
"description": "Number of new vulnerabilities detected"
|
||||
},
|
||||
"resolvedVulnerabilities": {
|
||||
"type": "integer",
|
||||
"description": "Number of resolved vulnerabilities"
|
||||
},
|
||||
"links": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"schedule": { "type": "string", "format": "uri" },
|
||||
"delta": { "type": "string", "format": "uri" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"type": "object",
|
||||
"additionalProperties": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
219
docs/legal/COMPLIANCE_ATTESTATION_FORM.md
Normal file
219
docs/legal/COMPLIANCE_ATTESTATION_FORM.md
Normal file
@@ -0,0 +1,219 @@
|
||||
# Compliance Attestation Form
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-01-25
|
||||
|
||||
This document describes the compliance attestation process for Stella Ops Community
|
||||
Plugin Grant users. For a fillable template, see `templates/self-attestation-form.md`.
|
||||
|
||||
---
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
The compliance attestation process allows organizations to demonstrate compliance
|
||||
with the Stella Ops Community Plugin Grant without enabling telemetry or undergoing
|
||||
formal audit. It provides a trust-based mechanism for license compliance verification.
|
||||
|
||||
---
|
||||
|
||||
## 2. Who Should Attest
|
||||
|
||||
Annual attestation is recommended for:
|
||||
|
||||
- Organizations using Stella Ops in production
|
||||
- Deployments approaching free tier limits (2+ environments, 500+ scans/day)
|
||||
- Organizations with data governance policies prohibiting telemetry
|
||||
- MSPs managing customer deployments
|
||||
|
||||
Attestation is **not required** for:
|
||||
- Non-production or evaluation use
|
||||
- Single-environment deployments well within limits
|
||||
- Organizations with active telemetry enabled
|
||||
|
||||
---
|
||||
|
||||
## 3. Attestation Components
|
||||
|
||||
### 3.1 Operator Information
|
||||
|
||||
| Field | Description | Example |
|
||||
|-------|-------------|---------|
|
||||
| Organization Name | Legal entity name | Acme Corporation |
|
||||
| Contact Name | Primary compliance contact | Jane Smith |
|
||||
| Contact Email | Email for compliance communications | compliance@acme.com |
|
||||
| Installation ID | From admin dashboard (optional) | inst_abc123xyz |
|
||||
| Attestation Date | Date form completed | 2026-01-25 |
|
||||
|
||||
### 3.2 Usage Declaration
|
||||
|
||||
Declare current usage levels:
|
||||
|
||||
**Environment Count:**
|
||||
- [ ] 1 Environment
|
||||
- [ ] 2 Environments
|
||||
- [ ] 3 Environments (maximum free tier)
|
||||
- [ ] More than 3 Environments (requires commercial license)
|
||||
|
||||
**Scan Volume (peak 24-hour period in past year):**
|
||||
- [ ] Under 100 scans/day
|
||||
- [ ] 100-499 scans/day
|
||||
- [ ] 500-999 scans/day (maximum free tier)
|
||||
- [ ] Over 999 scans/day (requires commercial license)
|
||||
|
||||
### 3.3 Distribution Declaration
|
||||
|
||||
If redistributing Stella Ops or Plugins:
|
||||
|
||||
- [ ] We do not redistribute Stella Ops or Plugins
|
||||
- [ ] We redistribute with LICENSE and NOTICE files preserved
|
||||
- [ ] We redistribute Plugins only (not core Stella Ops)
|
||||
- [ ] We include this Addendum verbatim in all distributions
|
||||
- [ ] We do not offer Stella Ops as a competing managed service
|
||||
|
||||
### 3.4 SaaS/MSP Declaration
|
||||
|
||||
Select the applicable scenario:
|
||||
|
||||
- [ ] **Internal Use Only:** Stella Ops is used only by our employees/contractors
|
||||
- [ ] **MSP Single-Tenant:** We host isolated instances for customers (license details below)
|
||||
- [ ] **Not Applicable:** We do not provide hosted services
|
||||
|
||||
If MSP Single-Tenant, specify:
|
||||
- Number of customer instances: ___
|
||||
- License type per instance:
|
||||
- [ ] Each customer has own license
|
||||
- [ ] Our commercial license covers all instances
|
||||
- [ ] Mix (specify below)
|
||||
|
||||
---
|
||||
|
||||
## 4. Certification Statement
|
||||
|
||||
By submitting this attestation, the undersigned certifies that:
|
||||
|
||||
1. The information provided is accurate to the best of their knowledge
|
||||
2. The organization's use of Stella Ops complies with BUSL-1.1 and the Community
|
||||
Plugin Grant
|
||||
3. They have authority to make this attestation on behalf of the organization
|
||||
4. They understand that false attestation may result in license termination
|
||||
|
||||
---
|
||||
|
||||
## 5. Submission Process
|
||||
|
||||
### Step 1: Download Template
|
||||
Copy the template from `docs/legal/templates/self-attestation-form.md`
|
||||
|
||||
### Step 2: Complete Form
|
||||
Fill in all required fields. Use "N/A" for non-applicable sections.
|
||||
|
||||
### Step 3: Internal Review
|
||||
Have appropriate internal stakeholders review:
|
||||
- Legal/Compliance team
|
||||
- IT/Platform team (for technical accuracy)
|
||||
- Management (for authorization)
|
||||
|
||||
### Step 4: Submit
|
||||
Send completed form to: compliance@stella-ops.org
|
||||
|
||||
**Subject line:** `Compliance Attestation - [Organization Name] - [Year]`
|
||||
|
||||
### Step 5: Confirmation
|
||||
- Acknowledgment within 10 business days
|
||||
- Confirmation letter issued if attestation accepted
|
||||
- Follow-up questions if clarification needed
|
||||
|
||||
---
|
||||
|
||||
## 6. Renewal
|
||||
|
||||
### 6.1 Annual Renewal
|
||||
|
||||
Attestation should be renewed annually:
|
||||
- **Preferred:** Within 30 days of attestation anniversary
|
||||
- **Grace period:** 60 days after anniversary
|
||||
- **Reminder:** stella-ops.org will send reminder 30 days before due date
|
||||
|
||||
### 6.2 Material Changes
|
||||
|
||||
Submit updated attestation within 30 days if:
|
||||
- Environment count increases
|
||||
- Scan volume regularly exceeds 80% of limit
|
||||
- Organization structure changes (merger, acquisition)
|
||||
- Deployment model changes (internal to MSP)
|
||||
|
||||
---
|
||||
|
||||
## 7. Record Retention
|
||||
|
||||
### 7.1 Attestor Retention
|
||||
|
||||
Organizations should retain:
|
||||
- Copy of submitted attestation
|
||||
- Supporting documentation (usage reports, dashboard screenshots)
|
||||
- Confirmation letter from stella-ops.org
|
||||
|
||||
**Recommended retention period:** 5 years
|
||||
|
||||
### 7.2 stella-ops.org Retention
|
||||
|
||||
stella-ops.org retains:
|
||||
- Submitted attestations: 5 years
|
||||
- Confirmation letters: Indefinitely
|
||||
- Supporting communications: 3 years
|
||||
|
||||
---
|
||||
|
||||
## 8. Frequently Asked Questions
|
||||
|
||||
### Q: Is attestation mandatory?
|
||||
|
||||
**A:** No. Attestation is voluntary and recommended. It provides documented evidence
|
||||
of compliance in case of future questions.
|
||||
|
||||
### Q: What if our usage changes after attesting?
|
||||
|
||||
**A:** Submit an updated attestation within 30 days of material changes. Good-faith
|
||||
updates are appreciated and do not trigger penalties.
|
||||
|
||||
### Q: Can we attest for multiple installations?
|
||||
|
||||
**A:** Yes. Use one form per installation, or contact compliance@stella-ops.org for
|
||||
a consolidated form for large deployments.
|
||||
|
||||
### Q: What happens if we can't attest to compliance?
|
||||
|
||||
**A:** Contact sales@stella-ops.org to discuss commercial licensing options. There's
|
||||
no penalty for recognizing a need to upgrade.
|
||||
|
||||
### Q: Is the attestation legally binding?
|
||||
|
||||
**A:** The attestation is a representation of fact. Knowingly false attestation may
|
||||
result in license termination. However, good-faith errors with prompt correction
|
||||
are not penalized.
|
||||
|
||||
---
|
||||
|
||||
## 9. Contact
|
||||
|
||||
**Attestation submissions:**
|
||||
compliance@stella-ops.org
|
||||
|
||||
**Questions about the process:**
|
||||
legal@stella-ops.org
|
||||
|
||||
**Commercial licensing:**
|
||||
sales@stella-ops.org
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- `templates/self-attestation-form.md` - Fillable template
|
||||
- `ENFORCEMENT_TELEMETRY_POLICY.md` - Audit and telemetry details
|
||||
- `LICENSE-ADDENDUM-COMMUNITY-PLUGIN-GRANT.md` - Full legal terms
|
||||
|
||||
---
|
||||
|
||||
*Document maintained by: Legal + Compliance Team*
|
||||
*Last review: 2026-01-25*
|
||||
299
docs/legal/ENFORCEMENT_TELEMETRY_POLICY.md
Normal file
299
docs/legal/ENFORCEMENT_TELEMETRY_POLICY.md
Normal file
@@ -0,0 +1,299 @@
|
||||
# Enforcement and Telemetry Policy
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-01-25
|
||||
|
||||
This document describes how stella-ops.org verifies compliance with the Community
|
||||
Plugin Grant and free tier limits, including audit rights, telemetry options, and
|
||||
privacy safeguards.
|
||||
|
||||
---
|
||||
|
||||
## 1. Compliance Philosophy
|
||||
|
||||
Stella Ops is committed to:
|
||||
|
||||
1. **Trust-based compliance** - We assume good faith from our users
|
||||
2. **Minimal intrusion** - Verification should not burden legitimate users
|
||||
3. **Privacy by design** - No collection of customer content or sensitive data
|
||||
4. **Transparency** - Clear documentation of what we collect and why
|
||||
|
||||
---
|
||||
|
||||
## 2. Audit Rights
|
||||
|
||||
### 2.1 When Audits May Occur
|
||||
|
||||
stella-ops.org reserves the right to request compliance verification:
|
||||
|
||||
- **Frequency:** No more than once per calendar year per licensee
|
||||
- **Notice:** Minimum 30 days written notice
|
||||
- **Scope:** Limited to verification of Environment count and Scan volume
|
||||
- **Trigger:** Audits may be initiated based on:
|
||||
- Routine sampling of licensees
|
||||
- Credible reports of non-compliance
|
||||
- Self-reported concerns from licensees
|
||||
|
||||
### 2.2 Audit Process
|
||||
|
||||
**Step 1: Notice**
|
||||
- Written notice via email to registered contact
|
||||
- Specifies audit scope and requested documentation
|
||||
- Provides minimum 30-day response window
|
||||
|
||||
**Step 2: Documentation Request**
|
||||
- Licensee provides requested information:
|
||||
- Number of active Environments
|
||||
- Scan volume metrics (e.g., from Stella Ops admin dashboard)
|
||||
- Deployment architecture summary
|
||||
- No access to scan content, vulnerabilities, or business data required
|
||||
|
||||
**Step 3: Review**
|
||||
- stella-ops.org reviews submitted documentation
|
||||
- May request clarification on ambiguous items
|
||||
- Typically completed within 15 business days
|
||||
|
||||
**Step 4: Resolution**
|
||||
- Compliant: Written confirmation provided
|
||||
- Minor variance: Grace period to remediate
|
||||
- Significant non-compliance: Commercial license discussion
|
||||
|
||||
### 2.3 Audit Safeguards
|
||||
|
||||
All audits are conducted with:
|
||||
|
||||
- **Confidentiality:** All submitted information treated as confidential business
|
||||
information under mutual NDA
|
||||
- **Data protection:** GDPR-compliant handling of any personal data
|
||||
- **Limited retention:** Audit documentation retained for maximum 3 years
|
||||
- **No content access:** We never request access to scan results, source code,
|
||||
or customer business data
|
||||
|
||||
---
|
||||
|
||||
## 3. Voluntary Telemetry
|
||||
|
||||
### 3.1 Telemetry Overview
|
||||
|
||||
Stella Ops provides an **optional** telemetry endpoint for users who wish to
|
||||
automate compliance reporting.
|
||||
|
||||
**Key principles:**
|
||||
- **Strictly opt-in:** Disabled by default
|
||||
- **Aggregate metrics only:** No detailed scan data
|
||||
- **Privacy-respecting:** No PII or customer content
|
||||
- **User-controlled:** Can be disabled at any time
|
||||
|
||||
### 3.2 What Telemetry Collects (When Enabled)
|
||||
|
||||
| Metric | Description | Purpose |
|
||||
|--------|-------------|---------|
|
||||
| `installation_id` | Anonymous installation identifier | Deduplicate reports |
|
||||
| `environment_count` | Number of active environments | License compliance |
|
||||
| `scan_count_24h` | Scans in rolling 24-hour period | License compliance |
|
||||
| `version` | Stella Ops version | Compatibility/support |
|
||||
| `timestamp` | Report timestamp | Time-series analysis |
|
||||
|
||||
### 3.3 What Telemetry Does NOT Collect
|
||||
|
||||
- Scan results or vulnerability data
|
||||
- Customer names or identifiers
|
||||
- IP addresses (beyond transport layer)
|
||||
- Source code or artifact contents
|
||||
- User credentials or tokens
|
||||
- Business-sensitive configuration
|
||||
|
||||
### 3.4 Enabling/Disabling Telemetry
|
||||
|
||||
**To enable:**
|
||||
```yaml
|
||||
# In stella-ops.yaml
|
||||
telemetry:
|
||||
enabled: true
|
||||
endpoint: https://telemetry.stella-ops.org/v1/report
|
||||
```
|
||||
|
||||
**To disable (default):**
|
||||
```yaml
|
||||
telemetry:
|
||||
enabled: false
|
||||
```
|
||||
|
||||
**Environment variable override:**
|
||||
```bash
|
||||
STELLAOPS_TELEMETRY_ENABLED=false
|
||||
```
|
||||
|
||||
### 3.5 Telemetry Data Handling
|
||||
|
||||
- **Transmission:** TLS 1.3 encrypted
|
||||
- **Storage:** Aggregated and anonymized within 24 hours
|
||||
- **Retention:** Raw reports retained for maximum 90 days
|
||||
- **Access:** Limited to license compliance team
|
||||
- **No sale:** Never sold or shared with third parties
|
||||
|
||||
---
|
||||
|
||||
## 4. Self-Attestation
|
||||
|
||||
### 4.1 Overview
|
||||
|
||||
As an alternative to telemetry, licensees may provide annual self-attestation
|
||||
of compliance. This is the recommended approach for organizations with strict
|
||||
data governance requirements.
|
||||
|
||||
### 4.2 Attestation Process
|
||||
|
||||
1. **Download form:** `docs/legal/templates/self-attestation-form.md`
|
||||
2. **Complete attestation:** Fill in required fields
|
||||
3. **Submit:** Email to compliance@stella-ops.org
|
||||
4. **Confirmation:** Receive acknowledgment within 10 business days
|
||||
|
||||
### 4.3 Attestation Frequency
|
||||
|
||||
- **Annual:** Submit once per calendar year
|
||||
- **Upon request:** May be requested as part of audit
|
||||
- **Voluntary updates:** Submit anytime if circumstances change
|
||||
|
||||
### 4.4 False Attestation
|
||||
|
||||
Knowingly providing false attestation information may result in:
|
||||
- Immediate termination of license rights
|
||||
- Requirement to obtain commercial license
|
||||
- Potential legal action for license violation
|
||||
|
||||
---
|
||||
|
||||
## 5. Compliance Verification Methods
|
||||
|
||||
### 5.1 Recommended: Built-in Dashboard
|
||||
|
||||
Stella Ops includes a compliance dashboard at `/admin/compliance`:
|
||||
|
||||
```
|
||||
Compliance Status
|
||||
─────────────────
|
||||
License Type: Community (Free Tier)
|
||||
Environments: 2 of 3 (within limit)
|
||||
Scans (24h): 456 of 999 (within limit)
|
||||
Status: COMPLIANT
|
||||
```
|
||||
|
||||
This dashboard can be used to:
|
||||
- Monitor current usage against limits
|
||||
- Generate compliance reports for audit
|
||||
- Export metrics for self-attestation
|
||||
|
||||
### 5.2 API-Based Verification
|
||||
|
||||
Compliance metrics are available via API:
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer $ADMIN_TOKEN" \
|
||||
https://your-instance/api/v1/admin/compliance/metrics
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"environment_count": 2,
|
||||
"environment_limit": 3,
|
||||
"scan_count_24h": 456,
|
||||
"scan_limit_24h": 999,
|
||||
"compliant": true,
|
||||
"timestamp": "2026-01-25T14:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 Log-Based Verification
|
||||
|
||||
For organizations that prefer log analysis:
|
||||
|
||||
```bash
|
||||
# Extract compliance metrics from logs
|
||||
grep "compliance_check" /var/log/stellaops/audit.log | tail -1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Remediation
|
||||
|
||||
### 6.1 Exceeding Limits
|
||||
|
||||
If you discover you've exceeded free tier limits:
|
||||
|
||||
1. **Immediate:** Usage may be throttled (see `30_QUOTA_ENFORCEMENT_FLOW1.md`)
|
||||
2. **Short-term:** Reduce environments or scan volume to return to compliance
|
||||
3. **Long-term:** Obtain commercial license for ongoing needs
|
||||
|
||||
### 6.2 Grace Period
|
||||
|
||||
For good-faith limit exceedances:
|
||||
- **First occurrence:** 30-day grace period to remediate
|
||||
- **Repeated occurrence:** 15-day grace period
|
||||
- **Intentional abuse:** No grace period; commercial license required immediately
|
||||
|
||||
### 6.3 Commercial License Transition
|
||||
|
||||
If you need to exceed free tier limits:
|
||||
- Contact sales@stella-ops.org
|
||||
- Licenses can be backdated to cover grace period
|
||||
- No penalty for good-faith users who remediate promptly
|
||||
|
||||
---
|
||||
|
||||
## 7. Privacy Commitments
|
||||
|
||||
stella-ops.org commits to the following privacy principles:
|
||||
|
||||
### 7.1 Data Minimization
|
||||
We collect only the minimum data necessary for license compliance verification.
|
||||
|
||||
### 7.2 Purpose Limitation
|
||||
Compliance data is used only for license verification, never for marketing or
|
||||
sold to third parties.
|
||||
|
||||
### 7.3 User Control
|
||||
- Telemetry is opt-in only
|
||||
- Self-attestation is always available as alternative
|
||||
- Users can request deletion of any collected data
|
||||
|
||||
### 7.4 GDPR Compliance
|
||||
For EU users:
|
||||
- Data Processing Agreement (DPA) available upon request
|
||||
- Right to access, rectify, and delete data
|
||||
- Data stored in EU-based infrastructure when EU endpoint selected
|
||||
|
||||
### 7.5 Contact
|
||||
|
||||
For privacy-related inquiries:
|
||||
- Email: privacy@stella-ops.org
|
||||
- DPO: dpo@stella-ops.org (EU users)
|
||||
|
||||
---
|
||||
|
||||
## 8. Questions and Support
|
||||
|
||||
**Compliance questions:**
|
||||
- Email: compliance@stella-ops.org
|
||||
|
||||
**Technical questions about telemetry:**
|
||||
- Documentation: `docs/admin/telemetry.md`
|
||||
- Support: support@stella-ops.org
|
||||
|
||||
**Commercial licensing:**
|
||||
- Email: sales@stella-ops.org
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- `LICENSE-ADDENDUM-COMMUNITY-PLUGIN-GRANT.md` - Full legal terms
|
||||
- `docs/legal/30_QUOTA_ENFORCEMENT_FLOW1.md` - Quota enforcement behavior
|
||||
- `docs/legal/templates/self-attestation-form.md` - Attestation form
|
||||
- `docs/admin/telemetry.md` - Technical telemetry configuration
|
||||
|
||||
---
|
||||
|
||||
*Document maintained by: Legal + Privacy Office*
|
||||
*Last review: 2026-01-25*
|
||||
@@ -1,4 +1,4 @@
|
||||
# Legal FAQ <EFBFBD> Free-Tier Quota & BUSL-1.1 Additional Use Grant
|
||||
# Legal FAQ - Free-Tier Quota & BUSL-1.1 Additional Use Grant
|
||||
|
||||
> **Operational behaviour (limits, counters, delays) is documented in**
|
||||
> [`30_QUOTA_ENFORCEMENT_FLOW1.md`](30_QUOTA_ENFORCEMENT_FLOW1.md).
|
||||
@@ -6,6 +6,12 @@
|
||||
> service or embedding it into another product while the free-tier limits are
|
||||
> in place.
|
||||
|
||||
> **Plugin developers:** See [`PLUGIN_DEVELOPER_FAQ.md`](PLUGIN_DEVELOPER_FAQ.md)
|
||||
> for plugin-specific licensing questions.
|
||||
>
|
||||
> **MSPs and SaaS providers:** See [`SAAS_MSP_GUIDANCE.md`](SAAS_MSP_GUIDANCE.md)
|
||||
> for detailed hosting scenarios.
|
||||
|
||||
---
|
||||
|
||||
## 1 ? Does enforcing a quota violate BUSL-1.1?
|
||||
@@ -45,7 +51,7 @@ obtained. Proprietary integration code does not have to be disclosed.
|
||||
The BUSL-1.1 Additional Use Grant prohibits providing Stella Ops as a hosted or
|
||||
managed service to third parties. SaaS/hosted use requires a commercial license.
|
||||
|
||||
## 5 <20> Is e-mail collection for the JWT legal?
|
||||
## 5 <20> Is e-mail collection for the JWT legal?
|
||||
|
||||
* **Purpose limitation (GDPR Art. 5-1 b):** address is used only to deliver the
|
||||
JWT or optional release notes.
|
||||
@@ -58,10 +64,23 @@ Hence the token workflow adheres to GDPR principles.
|
||||
|
||||
---
|
||||
|
||||
## 6 <20> Change-log
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [`PLUGIN_DEVELOPER_FAQ.md`](PLUGIN_DEVELOPER_FAQ.md) - Plugin development and distribution questions
|
||||
- [`SAAS_MSP_GUIDANCE.md`](SAAS_MSP_GUIDANCE.md) - SaaS and MSP hosting scenarios
|
||||
- [`ENFORCEMENT_TELEMETRY_POLICY.md`](ENFORCEMENT_TELEMETRY_POLICY.md) - Audit and telemetry details
|
||||
- [`COMPLIANCE_ATTESTATION_FORM.md`](COMPLIANCE_ATTESTATION_FORM.md) - Self-attestation process
|
||||
- [`LICENSE-ADDENDUM-COMMUNITY-PLUGIN-GRANT.md`](../../LICENSE-ADDENDUM-COMMUNITY-PLUGIN-GRANT.md) - Full addendum text
|
||||
|
||||
---
|
||||
|
||||
## 6 - Change-log
|
||||
|
||||
| Version | Date | Notes |
|
||||
|---------|------|-------|
|
||||
| **3.1** | 2026-01-25 | Added cross-references to Community Plugin Grant documentation. |
|
||||
| **3.0** | 2026-01-20 | Updated for BUSL-1.1 Additional Use Grant. |
|
||||
| **2.1** | 2026-01-20 | Updated for Apache-2.0 licensing (superseded by BUSL-1.1 in v3.0). |
|
||||
| **2.0** | 2025-07-16 | Removed runtime quota details; linked to new authoritative overview. |
|
||||
|
||||
@@ -126,6 +126,41 @@ The following are considered **aggregation**, not derivation:
|
||||
|
||||
**Rationale:** These components communicate via network protocols, APIs, or standard interfaces and are not linked into StellaOps binaries.
|
||||
|
||||
### 3.5 Plugin Distribution (Community Plugin Grant)
|
||||
|
||||
The Community Plugin Grant Addendum (`LICENSE-ADDENDUM-COMMUNITY-PLUGIN-GRANT.md`)
|
||||
provides additional terms for plugin development and distribution.
|
||||
|
||||
**When distributing StellaOps Plugins:**
|
||||
|
||||
```
|
||||
Plugin Distribution
|
||||
+-- Plugin code (your license)
|
||||
+-- Attribution to StellaOps
|
||||
+-- If derivative work:
|
||||
+-- LICENSE (BUSL-1.1)
|
||||
+-- LICENSE-ADDENDUM-COMMUNITY-PLUGIN-GRANT.md
|
||||
+-- NOTICE.md
|
||||
```
|
||||
|
||||
**Requirements by Plugin Type:**
|
||||
|
||||
| Plugin Type | License | Attribution | Include LICENSE | Include Addendum |
|
||||
|-------------|---------|-------------|-----------------|------------------|
|
||||
| API-only (no StellaOps code) | Your choice | Recommended | No | No |
|
||||
| Includes StellaOps code | BUSL-1.1 | Required | Yes | Yes |
|
||||
| Bundled with StellaOps | BUSL-1.1 | Required | Yes | Yes |
|
||||
| Competing managed service | Commercial | N/A | N/A | N/A |
|
||||
|
||||
**Not Allowed Without Commercial License:**
|
||||
- Redistributing plugins as part of a competing managed service offering
|
||||
- White-labeling StellaOps functionality through plugins
|
||||
- Embedding plugins in multi-tenant SaaS offerings to third parties
|
||||
|
||||
**See Also:**
|
||||
- `docs/legal/PLUGIN_DEVELOPER_FAQ.md` - Detailed plugin licensing FAQ
|
||||
- `docs/legal/SAAS_MSP_GUIDANCE.md` - SaaS and MSP hosting scenarios
|
||||
|
||||
---
|
||||
|
||||
## 4. Specific Dependency Analysis
|
||||
@@ -289,8 +324,18 @@ Sample configuration files (`etc/*.yaml.sample`) are:
|
||||
- [Apache 2.0 FAQ](https://www.apache.org/foundation/license-faq.html)
|
||||
- [SPDX License List](https://spdx.org/licenses/)
|
||||
- [REUSE Best Practices](https://reuse.software/tutorial/)
|
||||
- [BUSL-1.1 License Text](https://spdx.org/licenses/BUSL-1.1.html)
|
||||
|
||||
---
|
||||
|
||||
## 9. Related Documents
|
||||
|
||||
- `LICENSE-ADDENDUM-COMMUNITY-PLUGIN-GRANT.md` - Community Plugin Grant Addendum
|
||||
- `docs/legal/PLUGIN_DEVELOPER_FAQ.md` - Plugin developer FAQ
|
||||
- `docs/legal/SAAS_MSP_GUIDANCE.md` - SaaS and MSP guidance
|
||||
- `docs/legal/ENFORCEMENT_TELEMETRY_POLICY.md` - Audit and compliance policy
|
||||
|
||||
---
|
||||
|
||||
*Document maintained by: Legal + Security Guild*
|
||||
*Last review: 2026-01-20*
|
||||
*Last review: 2026-01-25*
|
||||
|
||||
291
docs/legal/PLUGIN_DEVELOPER_FAQ.md
Normal file
291
docs/legal/PLUGIN_DEVELOPER_FAQ.md
Normal file
@@ -0,0 +1,291 @@
|
||||
# Plugin Developer FAQ
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-01-25
|
||||
|
||||
This FAQ addresses common questions from plugin developers working with the Stella Ops
|
||||
Community Plugin Grant. For the full legal terms, see `LICENSE-ADDENDUM-COMMUNITY-PLUGIN-GRANT.md`
|
||||
in the repository root.
|
||||
|
||||
---
|
||||
|
||||
## General Questions
|
||||
|
||||
### Q1: What constitutes a "Plugin" under the Community Plugin Grant?
|
||||
|
||||
**A:** A Plugin is a separately packaged extension that interfaces with Stella Ops using
|
||||
documented public plugin APIs or integration points. This includes:
|
||||
|
||||
**Examples of Plugins:**
|
||||
- Custom vulnerability connectors (e.g., integrating a proprietary vulnerability database)
|
||||
- CI/CD integrations (e.g., Jenkins, GitLab CI, Azure DevOps plugins)
|
||||
- Output formatters (e.g., custom report templates, dashboard integrations)
|
||||
- Notification connectors (e.g., Slack, Teams, PagerDuty integrations)
|
||||
- Scanner analyzers (e.g., language-specific dependency parsers)
|
||||
- Policy gates (e.g., custom compliance rules)
|
||||
|
||||
**NOT Plugins (derivative works requiring BUSL-1.1 compliance):**
|
||||
- Modifications to Stella Ops core source code
|
||||
- Forks that include modified Stella Ops components
|
||||
- Extensions that copy substantial portions of Stella Ops internals
|
||||
|
||||
### Q2: Can I sell my plugin commercially?
|
||||
|
||||
**A:** Yes. You may develop and sell plugins commercially under license terms of your
|
||||
choosing (including proprietary terms), provided:
|
||||
|
||||
1. Your plugin does not include, copy, or modify Stella Ops source code; AND
|
||||
2. You comply with the attribution requirements (see Q4).
|
||||
|
||||
Your commercial plugin license is entirely separate from the BUSL-1.1 license covering
|
||||
Stella Ops itself.
|
||||
|
||||
### Q3: Do I need to open-source my plugin?
|
||||
|
||||
**A:** No. Plugins that interface with Stella Ops through public APIs do not need to be
|
||||
open-sourced. You may use any license you choose, including proprietary licenses.
|
||||
|
||||
**Exception:** If your plugin includes, copies, or modifies any portion of Stella Ops
|
||||
source code, it becomes a derivative work subject to BUSL-1.1.
|
||||
|
||||
### Q4: What attribution is required when distributing a plugin?
|
||||
|
||||
**A:** When distributing a plugin, you should:
|
||||
|
||||
1. **Acknowledge compatibility:** State that your plugin is designed for use with
|
||||
Stella Ops (e.g., "Compatible with Stella Ops Suite")
|
||||
|
||||
2. **Include license reference:** If your plugin distribution includes any Stella Ops
|
||||
components (even configuration samples), include the LICENSE and NOTICE files
|
||||
|
||||
3. **Link to source:** Provide a link to the Stella Ops source repository
|
||||
(https://git.stella-ops.org)
|
||||
|
||||
**Minimum attribution example:**
|
||||
```
|
||||
This plugin is designed for use with Stella Ops Suite.
|
||||
Stella Ops is licensed under BUSL-1.1. See https://git.stella-ops.org
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Usage Limits
|
||||
|
||||
### Q5: What counts as an "Environment"?
|
||||
|
||||
**A:** An Environment is a logically separated workspace within a Stella Ops installation.
|
||||
The free tier allows up to 3 Environments per installation.
|
||||
|
||||
**Each of these counts as one Environment:**
|
||||
- A "Development" environment for testing scans
|
||||
- A "Staging" environment for pre-production validation
|
||||
- A "Production" environment for live deployments
|
||||
- A tenant/workspace in a multi-tenant setup
|
||||
- A project or team workspace with isolated configuration
|
||||
|
||||
**These do NOT count as separate Environments:**
|
||||
- High-availability replicas of the same environment
|
||||
- Read replicas or cache nodes
|
||||
- Backup/disaster recovery instances (if not actively used)
|
||||
|
||||
**Example scenarios:**
|
||||
|
||||
| Scenario | Environment Count |
|
||||
|----------|------------------|
|
||||
| Single dev laptop installation | 1 |
|
||||
| Dev + Staging + Prod for one team | 3 |
|
||||
| Two separate teams, each with Dev + Prod | 4 (requires commercial license) |
|
||||
| MSP hosting 5 isolated customer instances | 5 (requires commercial license) |
|
||||
|
||||
### Q6: What counts as a "Scan"?
|
||||
|
||||
**A:** A Scan is one completed execution of Stella Ops' vulnerability or artifact analysis
|
||||
pipeline that produces a new result. The free tier allows up to 999 Scans per calendar day.
|
||||
|
||||
**Counts as a Scan:**
|
||||
- First-time scan of a container image (new hash)
|
||||
- Re-scan of a modified image (hash changed)
|
||||
- SBOM generation for a new artifact
|
||||
- VEX statement generation for new findings
|
||||
|
||||
**Does NOT count as a Scan:**
|
||||
- Cache hits (retrieving previously scanned results)
|
||||
- Viewing existing scan reports
|
||||
- Policy evaluation on cached data
|
||||
- API queries for existing results
|
||||
|
||||
**Deduplication:** Stella Ops uses hash-based deduplication. Scanning the same artifact
|
||||
multiple times only counts as one Scan if the hash hasn't changed.
|
||||
|
||||
### Q7: What happens if my users exceed the free limits?
|
||||
|
||||
**A:** If users of your plugin exceed the free tier limits (3 Environments or 999 Scans/day):
|
||||
|
||||
1. **They need a commercial license** - The user (not the plugin developer) is responsible
|
||||
for licensing compliance
|
||||
2. **Your plugin continues to work** - There's no technical enforcement in the plugin itself
|
||||
3. **Quota enforcement is server-side** - Stella Ops may introduce delays after limits
|
||||
are exceeded (see `docs/legal/30_QUOTA_ENFORCEMENT_FLOW1.md`)
|
||||
|
||||
As a plugin developer, you should:
|
||||
- Document the free tier limits in your plugin documentation
|
||||
- Recommend users contact stella-ops.org for commercial licensing if they exceed limits
|
||||
- Not build quota circumvention into your plugin
|
||||
|
||||
---
|
||||
|
||||
## Bundling & Distribution
|
||||
|
||||
### Q8: Can I bundle Stella Ops core with my plugin?
|
||||
|
||||
**A:** This depends on how you bundle:
|
||||
|
||||
**Allowed (aggregation):**
|
||||
- Shipping your plugin alongside Stella Ops as separate components
|
||||
- Docker Compose files that reference Stella Ops images
|
||||
- Helm charts that deploy Stella Ops as a dependency
|
||||
- Installation scripts that download Stella Ops separately
|
||||
|
||||
**Requires BUSL-1.1 compliance (derivative work):**
|
||||
- Embedding Stella Ops source code into your plugin
|
||||
- Modifying Stella Ops binaries and redistributing
|
||||
- Creating a single binary that includes Stella Ops components
|
||||
|
||||
**Requires commercial license:**
|
||||
- Bundling into a competing managed service offering
|
||||
- White-labeling Stella Ops functionality
|
||||
|
||||
### Q9: Can I create a plugin that modifies Stella Ops behavior at runtime?
|
||||
|
||||
**A:** Yes, if the modification uses documented extension points:
|
||||
|
||||
**Allowed:**
|
||||
- Plugins that register custom handlers via plugin APIs
|
||||
- Extensions that add new endpoints or processing steps
|
||||
- Integrations that intercept and transform data via documented hooks
|
||||
|
||||
**Not allowed without BUSL-1.1 derivative work compliance:**
|
||||
- Runtime patching of Stella Ops binaries
|
||||
- Monkey-patching internal classes or methods
|
||||
- Replacing core components at runtime
|
||||
|
||||
The key distinction is whether you're using **documented public APIs** (allowed) vs.
|
||||
**undocumented internal behavior** (derivative work).
|
||||
|
||||
---
|
||||
|
||||
## Commercial Considerations
|
||||
|
||||
### Q10: Can my plugin be used with Stella Ops commercial/SaaS offerings?
|
||||
|
||||
**A:** Yes. Plugins designed for the Community Plugin Grant are compatible with commercial
|
||||
Stella Ops deployments. Commercial customers may use community plugins subject to their
|
||||
commercial license terms.
|
||||
|
||||
### Q11: Do I need Licensor approval to publish a plugin?
|
||||
|
||||
**A:** No. You do not need approval from stella-ops.org to:
|
||||
- Develop plugins
|
||||
- Publish plugins (open source or commercial)
|
||||
- List plugins in third-party marketplaces
|
||||
|
||||
However, stella-ops.org may maintain an official plugin registry with quality/security
|
||||
standards for listed plugins.
|
||||
|
||||
### Q12: Can MSPs provide plugins to their managed customers?
|
||||
|
||||
**A:** Yes, with these considerations:
|
||||
|
||||
1. **Plugin distribution:** MSPs can freely distribute plugins to customers
|
||||
2. **Stella Ops licensing:** Each customer deployment must comply with BUSL-1.1:
|
||||
- Within free tier limits; OR
|
||||
- Covered by MSP's commercial license; OR
|
||||
- Customer has their own commercial license
|
||||
|
||||
See `docs/legal/SAAS_MSP_GUIDANCE.md` for detailed MSP scenarios.
|
||||
|
||||
---
|
||||
|
||||
## Edge Cases
|
||||
|
||||
### Q13: Does the Community Plugin Grant apply to unofficial API integrations?
|
||||
|
||||
**A:** The grant specifically covers plugins using "documented public plugin APIs or
|
||||
integration points." For unofficial or undocumented APIs:
|
||||
|
||||
- Using undocumented APIs is at your own risk (they may change without notice)
|
||||
- The Community Plugin Grant still applies if you're not modifying source code
|
||||
- Relying on internal implementation details may create a derivative work
|
||||
|
||||
**Recommendation:** Use documented APIs for stable, supported integration.
|
||||
|
||||
### Q14: Can I fork Stella Ops and call it something else?
|
||||
|
||||
**A:** Forking is allowed under BUSL-1.1, but:
|
||||
|
||||
1. **BUSL-1.1 applies to the fork** - Production use requires compliance with the
|
||||
Additional Use Grant or a commercial license
|
||||
2. **Attribution required** - You must preserve LICENSE, NOTICE, and copyright notices
|
||||
3. **No trademark use** - You may not use Stella Ops trademarks for your fork
|
||||
4. **Change Date applies** - After the Change Date (2030-01-20), the fork converts to
|
||||
Apache-2.0
|
||||
|
||||
### Q15: What if my plugin becomes popular and used beyond free tier limits?
|
||||
|
||||
**A:** Success is good! If your plugin enables usage beyond free tier limits:
|
||||
|
||||
1. **Users are responsible for licensing** - Not you as the plugin developer
|
||||
2. **Consider partnership** - Contact stella-ops.org about potential partnership or
|
||||
revenue sharing arrangements
|
||||
3. **Document clearly** - Ensure your plugin documentation explains licensing requirements
|
||||
|
||||
### Q16: Can I host a free scanning service for the community using my plugin?
|
||||
|
||||
**A:** The BUSL-1.1 restriction specifically targets "public multi-tenant **paid** hosting."
|
||||
Non-commercial, free-of-charge hosting for community benefit may be eligible for the
|
||||
Community Program.
|
||||
|
||||
**Potentially eligible:**
|
||||
- Free scanning for open source projects
|
||||
- Academic/educational free access
|
||||
- Non-profit services for other non-profits
|
||||
|
||||
**Not eligible (requires commercial license):**
|
||||
- "Free tier" that upsells to paid services
|
||||
- Free scanning bundled with paid consulting
|
||||
- Any scenario where the free service drives commercial revenue
|
||||
|
||||
**Process:** Apply to the Community Program at community@stella-ops.org. Approval is
|
||||
not automatic and is evaluated based on genuine community benefit.
|
||||
|
||||
See `docs/legal/SAAS_MSP_GUIDANCE.md` Section 4.3 for detailed guidance.
|
||||
|
||||
---
|
||||
|
||||
## Getting Help
|
||||
|
||||
**Technical questions about plugin development:**
|
||||
- Documentation: `docs/plugins/`
|
||||
- Community forum: https://community.stella-ops.org
|
||||
|
||||
**Licensing questions:**
|
||||
- Email: legal@stella-ops.org
|
||||
- FAQ: This document and `docs/legal/LEGAL_FAQ_QUOTA.md`
|
||||
|
||||
**Commercial licensing:**
|
||||
- Email: sales@stella-ops.org
|
||||
- Website: https://stella-ops.org/pricing
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- `LICENSE-ADDENDUM-COMMUNITY-PLUGIN-GRANT.md` - Full legal terms
|
||||
- `docs/legal/LEGAL_FAQ_QUOTA.md` - Quota and free tier FAQ
|
||||
- `docs/legal/SAAS_MSP_GUIDANCE.md` - MSP and SaaS guidance
|
||||
- `docs/legal/LICENSE-COMPATIBILITY.md` - License compatibility for dependencies
|
||||
|
||||
---
|
||||
|
||||
*Document maintained by: Legal + Developer Relations*
|
||||
*Last review: 2026-01-25*
|
||||
@@ -6,10 +6,21 @@ authoritative artifacts.
|
||||
|
||||
## Canonical documents
|
||||
|
||||
### Core License Files (Repository Root)
|
||||
- Project license (BUSL-1.1 + Additional Use Grant): `LICENSE`
|
||||
- Community Plugin Grant Addendum: `LICENSE-ADDENDUM-COMMUNITY-PLUGIN-GRANT.md`
|
||||
- Third-party notices: `NOTICE.md`
|
||||
|
||||
### Compliance & Compatibility
|
||||
- Full dependency inventory: `docs/legal/THIRD-PARTY-DEPENDENCIES.md`
|
||||
- License compatibility guidance: `docs/legal/LICENSE-COMPATIBILITY.md`
|
||||
- Additional Use Grant summary and quotas: `docs/legal/LEGAL_FAQ_QUOTA.md`
|
||||
- Regulator-grade threat and evidence model: `docs/legal/LEGAL_COMPLIANCE.md`
|
||||
- Cryptography compliance notes: `docs/legal/crypto-compliance-review.md`
|
||||
|
||||
### Plugin & Distribution Guidance
|
||||
- Plugin developer FAQ: `docs/legal/PLUGIN_DEVELOPER_FAQ.md`
|
||||
- SaaS and MSP licensing guidance: `docs/legal/SAAS_MSP_GUIDANCE.md`
|
||||
- Enforcement and telemetry policy: `docs/legal/ENFORCEMENT_TELEMETRY_POLICY.md`
|
||||
- Compliance attestation process: `docs/legal/COMPLIANCE_ATTESTATION_FORM.md`
|
||||
- Self-attestation form template: `docs/legal/templates/self-attestation-form.md`
|
||||
|
||||
356
docs/legal/SAAS_MSP_GUIDANCE.md
Normal file
356
docs/legal/SAAS_MSP_GUIDANCE.md
Normal file
@@ -0,0 +1,356 @@
|
||||
# SaaS and MSP Licensing Guidance
|
||||
|
||||
**Document Version:** 1.0.0
|
||||
**Last Updated:** 2026-01-25
|
||||
|
||||
This document provides detailed guidance on Stella Ops licensing for SaaS providers,
|
||||
Managed Service Providers (MSPs), and hosting scenarios. For the full legal terms,
|
||||
see `LICENSE-ADDENDUM-COMMUNITY-PLUGIN-GRANT.md`.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
The Stella Ops BUSL-1.1 license with Community Plugin Grant restricts providing Stella
|
||||
Ops as a commercial hosted service to third parties. This document clarifies what is
|
||||
and isn't permitted under different hosting scenarios.
|
||||
|
||||
**Key Principle:** The restriction targets commercial offerings that compete with
|
||||
Stella Ops' own hosted services, not legitimate internal use or isolated customer
|
||||
deployments.
|
||||
|
||||
---
|
||||
|
||||
## 1. Prohibited: Multi-Tenant SaaS Offerings
|
||||
|
||||
The following are **NOT permitted** without a commercial license:
|
||||
|
||||
### 1.1 Public SaaS Platform
|
||||
|
||||
**Prohibited:** Operating a multi-tenant SaaS platform that provides Stella Ops
|
||||
functionality to paying customers.
|
||||
|
||||
**Example (prohibited):**
|
||||
```
|
||||
AcmeScan.io
|
||||
├── Customer A (paying subscriber)
|
||||
├── Customer B (paying subscriber)
|
||||
├── Customer C (paying subscriber)
|
||||
└── Shared Stella Ops infrastructure
|
||||
```
|
||||
|
||||
**Why prohibited:** This directly competes with Stella Ops' commercial SaaS offering.
|
||||
|
||||
### 1.2 White-Label Hosting
|
||||
|
||||
**Prohibited:** Rebranding Stella Ops and selling it as your own hosted product.
|
||||
|
||||
**Example (prohibited):**
|
||||
```
|
||||
"PowerScan Pro" (white-labeled Stella Ops)
|
||||
├── Sold as monthly subscription
|
||||
├── Marketed as proprietary technology
|
||||
└── Runs on shared infrastructure
|
||||
```
|
||||
|
||||
**Why prohibited:** This is commercial redistribution as a competing service.
|
||||
|
||||
### 1.3 Embedded SaaS Features
|
||||
|
||||
**Prohibited:** Embedding Stella Ops scanning as a feature in your commercial SaaS product.
|
||||
|
||||
**Example (prohibited):**
|
||||
```
|
||||
AcmeDevPlatform.com (commercial SaaS)
|
||||
├── Code repository feature
|
||||
├── CI/CD pipeline feature
|
||||
├── "Security Scanning" feature <- Powered by embedded Stella Ops
|
||||
└── Charged as part of subscription
|
||||
```
|
||||
|
||||
**Why prohibited:** Stella Ops functionality is being monetized as part of a third-party
|
||||
service offering.
|
||||
|
||||
---
|
||||
|
||||
## 2. Permitted: Internal Use
|
||||
|
||||
The following **ARE permitted** under the Community Plugin Grant:
|
||||
|
||||
### 2.1 Internal Enterprise Deployment
|
||||
|
||||
**Permitted:** Deploying Stella Ops for your organization's internal use.
|
||||
|
||||
**Example (permitted):**
|
||||
```
|
||||
Acme Corp Internal
|
||||
├── Development team scans
|
||||
├── Security team analysis
|
||||
├── Compliance reporting
|
||||
└── Accessed only by Acme employees/contractors
|
||||
```
|
||||
|
||||
**Why permitted:** Internal use for the licensee's own business operations.
|
||||
|
||||
### 2.2 Internal Platform Team
|
||||
|
||||
**Permitted:** A platform/DevOps team providing Stella Ops to internal development teams.
|
||||
|
||||
**Example (permitted):**
|
||||
```
|
||||
Acme Corp Platform Team
|
||||
├── Hosts Stella Ops on internal infrastructure
|
||||
├── Provides scanning service to:
|
||||
│ ├── Team Alpha (internal)
|
||||
│ ├── Team Beta (internal)
|
||||
│ └── Team Gamma (internal)
|
||||
└── All users are Acme employees
|
||||
```
|
||||
|
||||
**Why permitted:** All users are within the same organization.
|
||||
|
||||
### 2.3 Subsidiary/Affiliate Use
|
||||
|
||||
**Permitted:** Parent company hosting for subsidiaries under common control.
|
||||
|
||||
**Example (permitted):**
|
||||
```
|
||||
Acme Holdings
|
||||
├── Acme Corp (subsidiary) - uses hosted Stella Ops
|
||||
├── Acme Europe (subsidiary) - uses hosted Stella Ops
|
||||
└── Acme Asia (subsidiary) - uses hosted Stella Ops
|
||||
```
|
||||
|
||||
**Why permitted:** Affiliates under common control are treated as one organization.
|
||||
|
||||
---
|
||||
|
||||
## 3. Permitted with Conditions: MSP Single-Tenant Hosting
|
||||
|
||||
Managed Service Providers may host Stella Ops for customers under specific conditions.
|
||||
|
||||
### 3.1 Single-Tenant Isolated Deployments
|
||||
|
||||
**Permitted (with commercial license):** MSP hosting separate Stella Ops instances for
|
||||
each customer.
|
||||
|
||||
**Example (permitted with commercial license):**
|
||||
```
|
||||
AcmeMSP Infrastructure
|
||||
├── Customer A Instance (isolated)
|
||||
│ ├── Dedicated Stella Ops deployment
|
||||
│ ├── Customer A data only
|
||||
│ └── Covered by AcmeMSP commercial license
|
||||
├── Customer B Instance (isolated)
|
||||
│ ├── Dedicated Stella Ops deployment
|
||||
│ ├── Customer B data only
|
||||
│ └── Covered by AcmeMSP commercial license
|
||||
└── No shared infrastructure between customers
|
||||
```
|
||||
|
||||
**Requirements:**
|
||||
- Each instance must be fully isolated
|
||||
- MSP must have commercial license covering all instances
|
||||
- Or each customer must have their own commercial license
|
||||
|
||||
### 3.2 Customer-Licensed Deployments
|
||||
|
||||
**Permitted:** MSP managing infrastructure where customer holds the license.
|
||||
|
||||
**Example (permitted):**
|
||||
```
|
||||
AcmeMSP (infrastructure only)
|
||||
├── Customer A Infrastructure
|
||||
│ ├── Customer A's Stella Ops license
|
||||
│ ├── MSP manages infrastructure
|
||||
│ └── Customer controls license compliance
|
||||
└── Customer B Infrastructure
|
||||
├── Customer B's Stella Ops license
|
||||
└── MSP manages infrastructure
|
||||
```
|
||||
|
||||
**Why permitted:** The customer (not MSP) is the licensee; MSP provides only
|
||||
infrastructure management.
|
||||
|
||||
---
|
||||
|
||||
## 4. Gray Areas: Guidance for Common Scenarios
|
||||
|
||||
### 4.1 Consulting with Temporary Access
|
||||
|
||||
**Scenario:** Security consultant deploys Stella Ops at client site for an engagement.
|
||||
|
||||
**Analysis:**
|
||||
- If consultant's license: Consultant needs commercial license for third-party use
|
||||
- If client's license: Client uses their free tier or commercial license
|
||||
|
||||
**Recommendation:** Client should obtain their own license; consultant assists with
|
||||
deployment.
|
||||
|
||||
### 4.2 Training/Demo Environments
|
||||
|
||||
**Scenario:** Providing training environments with Stella Ops to external trainees.
|
||||
|
||||
**Analysis:**
|
||||
- Temporary, non-production training: Generally permitted under non-production use
|
||||
- Ongoing access for trainees: May require commercial license depending on duration
|
||||
|
||||
**Recommendation:** Contact legal@stella-ops.org for training program licensing.
|
||||
|
||||
### 4.3 Non-Commercial Community Hosting
|
||||
|
||||
**Scenario:** Hosting Stella Ops scanning as a free service for community benefit.
|
||||
|
||||
The BUSL-1.1 restriction specifically targets "public multi-tenant **paid** hosting."
|
||||
Non-commercial hosting for community benefit may be eligible for the Community Program.
|
||||
|
||||
**Examples of potentially eligible scenarios:**
|
||||
- Free scanning services for open source projects
|
||||
- Academic/educational institutions providing free access to students
|
||||
- Non-profit organizations providing free services to other non-profits
|
||||
- Community-run instances for local developer communities
|
||||
|
||||
**Requirements for Community Program consideration:**
|
||||
1. Service must be genuinely free (no fees, subscriptions, or required purchases)
|
||||
2. Service must not be a loss-leader for commercial offerings
|
||||
3. Service must not compete directly with Licensor's commercial offerings
|
||||
4. Organization must apply and be approved by Licensor
|
||||
|
||||
**Analysis:**
|
||||
- Non-commercial, community benefit: Contact community@stella-ops.org for evaluation
|
||||
- If charging any fees: Requires commercial license (not eligible for Community Program)
|
||||
- If bundled with paid services: Requires commercial license
|
||||
|
||||
**Recommendation:** Apply for Community Program at https://stella-ops.org/community
|
||||
|
||||
**Important:** Community Program approval is not automatic. Licensor reserves the right
|
||||
to evaluate each application based on community benefit, competitive impact, and
|
||||
alignment with program goals.
|
||||
|
||||
### 4.4 Reseller/Channel Partner
|
||||
|
||||
**Scenario:** Reselling Stella Ops commercial licenses with implementation services.
|
||||
|
||||
**Analysis:**
|
||||
- Reselling licenses: Requires authorized reseller agreement
|
||||
- Implementation services: Permitted under customer's license
|
||||
|
||||
**Recommendation:** Contact sales@stella-ops.org for reseller program details.
|
||||
|
||||
---
|
||||
|
||||
## 5. Compliance Checklist
|
||||
|
||||
### For Internal Deployments
|
||||
|
||||
- [ ] All users are employees, contractors, or affiliates of the licensee
|
||||
- [ ] Deployment is within free tier limits (3 environments, 999 scans/day) OR
|
||||
commercial license obtained
|
||||
- [ ] LICENSE and NOTICE files preserved
|
||||
- [ ] No third-party access to functionality
|
||||
|
||||
### For MSP Deployments
|
||||
|
||||
- [ ] Each customer instance is fully isolated
|
||||
- [ ] Either MSP or customer holds valid license for each instance
|
||||
- [ ] No shared multi-tenant infrastructure
|
||||
- [ ] Clear documentation of license responsibility
|
||||
- [ ] Annual compliance attestation completed
|
||||
|
||||
### For Any Hosted Scenario
|
||||
|
||||
- [ ] Not marketed as competing SaaS product
|
||||
- [ ] Not white-labeled or rebranded
|
||||
- [ ] Not embedded in commercial SaaS offering
|
||||
- [ ] Attribution requirements met
|
||||
|
||||
---
|
||||
|
||||
## 6. Decision Tree
|
||||
|
||||
```
|
||||
Is Stella Ops functionality being provided to third parties?
|
||||
│
|
||||
├─ NO → Internal use permitted (within free tier or with commercial license)
|
||||
│
|
||||
└─ YES → Is it a commercial offering (paid or part of paid service)?
|
||||
│
|
||||
├─ NO (genuinely free, community benefit)
|
||||
│ │
|
||||
│ ├─ Apply for Community Program (community@stella-ops.org)
|
||||
│ │
|
||||
│ └─ If approved → Permitted under Community Program terms
|
||||
│ If not approved → Commercial license required
|
||||
│
|
||||
└─ YES (paid, or free-as-loss-leader for paid services)
|
||||
│
|
||||
└─ Is each customer fully isolated (single-tenant)?
|
||||
│
|
||||
├─ NO → Commercial SaaS license required
|
||||
│ (contact sales@stella-ops.org)
|
||||
│
|
||||
└─ YES → MSP single-tenant model
|
||||
│
|
||||
├─ MSP holds commercial license covering all instances
|
||||
│ → Permitted
|
||||
│
|
||||
└─ Each customer holds their own license
|
||||
→ Permitted (MSP provides infrastructure only)
|
||||
```
|
||||
|
||||
**Key distinction:** The restriction targets "public multi-tenant **paid** hosting."
|
||||
Non-commercial hosting for genuine community benefit may qualify for the Community Program,
|
||||
but requires explicit approval from Licensor.
|
||||
|
||||
---
|
||||
|
||||
## 7. Examples of Compliance Violations
|
||||
|
||||
The following are examples of arrangements that would violate the license:
|
||||
|
||||
1. **"Vulnerability Scanning as a Service"** - Public signup for scanning services
|
||||
powered by Stella Ops without commercial license
|
||||
|
||||
2. **DevSecOps Platform Bundle** - Including Stella Ops scanning in a paid platform
|
||||
subscription without commercial license
|
||||
|
||||
3. **Shared MSP Instance** - Multiple MSP customers sharing a single Stella Ops
|
||||
deployment
|
||||
|
||||
4. **"Free Tier Arbitrage"** - Running multiple free-tier installations to serve
|
||||
third-party customers
|
||||
|
||||
5. **Competitive Forking** - Forking Stella Ops and offering it as a competing
|
||||
hosted service
|
||||
|
||||
---
|
||||
|
||||
## 8. Getting Commercial License
|
||||
|
||||
If your use case requires a commercial license:
|
||||
|
||||
**Contact:**
|
||||
- Email: sales@stella-ops.org
|
||||
- Website: https://stella-ops.org/pricing
|
||||
|
||||
**License options include:**
|
||||
- Per-environment licensing
|
||||
- Unlimited scan licensing
|
||||
- MSP/reseller programs
|
||||
- OEM/embedded licensing
|
||||
|
||||
**Volume discounts** available for MSPs and enterprise deployments.
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- `LICENSE-ADDENDUM-COMMUNITY-PLUGIN-GRANT.md` - Full legal terms
|
||||
- `docs/legal/LEGAL_FAQ_QUOTA.md` - Quota and free tier FAQ
|
||||
- `docs/legal/PLUGIN_DEVELOPER_FAQ.md` - Plugin developer questions
|
||||
- `docs/legal/ENFORCEMENT_TELEMETRY_POLICY.md` - Audit and compliance verification
|
||||
|
||||
---
|
||||
|
||||
*Document maintained by: Legal + Sales Operations*
|
||||
*Last review: 2026-01-25*
|
||||
188
docs/legal/templates/self-attestation-form.md
Normal file
188
docs/legal/templates/self-attestation-form.md
Normal file
@@ -0,0 +1,188 @@
|
||||
# Stella Ops Compliance Self-Attestation Form
|
||||
|
||||
**Form Version:** 1.0.0
|
||||
**Attestation Period:** [YEAR]
|
||||
|
||||
---
|
||||
|
||||
## Instructions
|
||||
|
||||
1. Complete all sections marked with `[ ]` or `___`
|
||||
2. Replace placeholder text `[...]` with your information
|
||||
3. Have an authorized representative sign
|
||||
4. Submit to: compliance@stella-ops.org
|
||||
5. Retain a copy for your records
|
||||
|
||||
---
|
||||
|
||||
## Section 1: Operator Information
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Organization Legal Name** | [Full legal name of organization] |
|
||||
| **Primary Contact Name** | [Name of compliance contact] |
|
||||
| **Primary Contact Email** | [Email address] |
|
||||
| **Primary Contact Phone** | [Phone number - optional] |
|
||||
| **Mailing Address** | [Business address] |
|
||||
| **Installation ID** | [From /admin/compliance dashboard, or "Not Available"] |
|
||||
| **Attestation Date** | [YYYY-MM-DD] |
|
||||
|
||||
---
|
||||
|
||||
## Section 2: Usage Declaration
|
||||
|
||||
### 2.1 Environment Count
|
||||
|
||||
Current number of active Environments in this installation:
|
||||
|
||||
- [ ] 1 Environment
|
||||
- [ ] 2 Environments
|
||||
- [ ] 3 Environments
|
||||
- [ ] More than 3 Environments
|
||||
|
||||
If more than 3 Environments, commercial license reference: _______________
|
||||
|
||||
### 2.2 Scan Volume
|
||||
|
||||
Peak daily scan volume (new hash scans) in the past 12 months:
|
||||
|
||||
- [ ] Under 100 scans/day
|
||||
- [ ] 100 - 499 scans/day
|
||||
- [ ] 500 - 999 scans/day
|
||||
- [ ] Over 999 scans/day
|
||||
|
||||
If over 999 scans/day, commercial license reference: _______________
|
||||
|
||||
### 2.3 Usage Metrics Source
|
||||
|
||||
How were the above metrics determined?
|
||||
|
||||
- [ ] Stella Ops admin dashboard
|
||||
- [ ] API metrics endpoint
|
||||
- [ ] Log analysis
|
||||
- [ ] Estimate based on operational knowledge
|
||||
- [ ] Other: _______________
|
||||
|
||||
---
|
||||
|
||||
## Section 3: Distribution Declaration
|
||||
|
||||
### 3.1 Redistribution Status
|
||||
|
||||
- [ ] We do NOT redistribute Stella Ops or Stella Ops Plugins
|
||||
- [ ] We redistribute Stella Ops (complete Section 3.2)
|
||||
- [ ] We redistribute Plugins only (complete Section 3.3)
|
||||
|
||||
### 3.2 Stella Ops Redistribution (if applicable)
|
||||
|
||||
- [ ] LICENSE file included in all distributions
|
||||
- [ ] NOTICE.md file included in all distributions
|
||||
- [ ] LICENSE-ADDENDUM-COMMUNITY-PLUGIN-GRANT.md included
|
||||
- [ ] Modified files marked with change notices
|
||||
- [ ] Not offered as competing managed service
|
||||
|
||||
Distribution channels: _______________
|
||||
|
||||
### 3.3 Plugin Redistribution (if applicable)
|
||||
|
||||
- [ ] Plugin does not include Stella Ops source code
|
||||
- [ ] Attribution to Stella Ops included
|
||||
- [ ] Plugin documentation references Stella Ops licensing
|
||||
|
||||
Plugin name(s): _______________
|
||||
|
||||
---
|
||||
|
||||
## Section 4: SaaS / MSP Declaration
|
||||
|
||||
### 4.1 Deployment Model
|
||||
|
||||
Select ONE:
|
||||
|
||||
- [ ] **Internal Use Only**
|
||||
- Stella Ops accessed only by our employees, contractors, and affiliates
|
||||
- No third-party access to Stella Ops functionality
|
||||
|
||||
- [ ] **MSP Single-Tenant Hosting**
|
||||
- We host isolated Stella Ops instances for customers
|
||||
- Complete Section 4.2
|
||||
|
||||
- [ ] **Commercial SaaS License**
|
||||
- We have a commercial license for SaaS/hosted use
|
||||
- License reference: _______________
|
||||
|
||||
### 4.2 MSP Details (if applicable)
|
||||
|
||||
Number of customer instances hosted: _______________
|
||||
|
||||
License coverage:
|
||||
- [ ] Our commercial license covers all customer instances
|
||||
- [ ] Each customer has their own Stella Ops license
|
||||
- [ ] Mixed (describe): _______________
|
||||
|
||||
Instance isolation:
|
||||
- [ ] Each customer has dedicated infrastructure (compute, storage)
|
||||
- [ ] No data sharing between customer instances
|
||||
- [ ] Customers cannot access each other's data or results
|
||||
|
||||
---
|
||||
|
||||
## Section 5: Certification
|
||||
|
||||
I certify that:
|
||||
|
||||
1. [ ] The information in this attestation is accurate and complete to the best of
|
||||
my knowledge
|
||||
|
||||
2. [ ] Our organization's use of Stella Ops complies with the Business Source
|
||||
License 1.1 and the Community Plugin Grant Addendum
|
||||
|
||||
3. [ ] I am authorized to make this attestation on behalf of the organization
|
||||
named above
|
||||
|
||||
4. [ ] I understand that knowingly providing false information may result in
|
||||
termination of license rights
|
||||
|
||||
5. [ ] I will notify stella-ops.org within 30 days of any material changes to
|
||||
the information provided
|
||||
|
||||
---
|
||||
|
||||
## Section 6: Signature
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| **Printed Name** | ___________________________ |
|
||||
| **Title/Role** | ___________________________ |
|
||||
| **Signature** | ___________________________ |
|
||||
| **Date** | ___________________________ |
|
||||
|
||||
---
|
||||
|
||||
## Section 7: Internal Use Only (stella-ops.org)
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Received Date | |
|
||||
| Reviewed By | |
|
||||
| Review Date | |
|
||||
| Status | [ ] Accepted [ ] Clarification Needed [ ] Referred to Sales |
|
||||
| Confirmation Sent | |
|
||||
| Notes | |
|
||||
|
||||
---
|
||||
|
||||
## Submission
|
||||
|
||||
**Email completed form to:** compliance@stella-ops.org
|
||||
|
||||
**Subject line:** `Compliance Attestation - [Organization Name] - [Year]`
|
||||
|
||||
**Attachments (optional but recommended):**
|
||||
- Screenshot of /admin/compliance dashboard
|
||||
- Usage report export (if available)
|
||||
|
||||
---
|
||||
|
||||
*Form version 1.0.0 | Effective 2026-01-25*
|
||||
*Questions? Contact legal@stella-ops.org*
|
||||
358
docs/modules/attestor/diagrams/trust-architecture.md
Normal file
358
docs/modules/attestor/diagrams/trust-architecture.md
Normal file
@@ -0,0 +1,358 @@
|
||||
# Trust Architecture Diagrams
|
||||
|
||||
> Sprint: SPRINT_20260125_003 - WORKFLOW-008
|
||||
> Last updated: 2026-01-25
|
||||
|
||||
This document provides architectural diagrams for the StellaOps TUF-based trust
|
||||
distribution system.
|
||||
|
||||
---
|
||||
|
||||
## 1. Trust Hierarchy
|
||||
|
||||
The TUF trust hierarchy showing roles and key relationships.
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "TUF Roles & Keys"
|
||||
ROOT[("Root<br/>(threshold: 3/5)")]
|
||||
TARGETS[("Targets<br/>(threshold: 1)")]
|
||||
SNAPSHOT[("Snapshot<br/>(threshold: 1)")]
|
||||
TIMESTAMP[("Timestamp<br/>(threshold: 1)")]
|
||||
end
|
||||
|
||||
subgraph "Trust Targets"
|
||||
REKOR_KEY["Rekor Public Key<br/>rekor-key-v1.pub"]
|
||||
FULCIO_CHAIN["Fulcio Chain<br/>fulcio-chain.pem"]
|
||||
SERVICE_MAP["Service Map<br/>sigstore-services-v1.json"]
|
||||
ORG_KEY["Org Signing Key<br/>org-signing-key.pub"]
|
||||
end
|
||||
|
||||
ROOT --> TARGETS
|
||||
ROOT --> SNAPSHOT
|
||||
ROOT --> TIMESTAMP
|
||||
SNAPSHOT --> TARGETS
|
||||
TIMESTAMP --> SNAPSHOT
|
||||
TARGETS --> REKOR_KEY
|
||||
TARGETS --> FULCIO_CHAIN
|
||||
TARGETS --> SERVICE_MAP
|
||||
TARGETS --> ORG_KEY
|
||||
|
||||
style ROOT fill:#ff6b6b,stroke:#333,stroke-width:2px
|
||||
style TARGETS fill:#4ecdc4,stroke:#333
|
||||
style SNAPSHOT fill:#45b7d1,stroke:#333
|
||||
style TIMESTAMP fill:#96ceb4,stroke:#333
|
||||
```
|
||||
|
||||
### Role Descriptions
|
||||
|
||||
| Role | Purpose | Update Frequency |
|
||||
|------|---------|-----------------|
|
||||
| Root | Ultimate trust anchor, defines all other roles | Rarely (ceremony) |
|
||||
| Targets | Lists trusted targets with hashes | When targets change |
|
||||
| Snapshot | Point-in-time view of all metadata | With targets |
|
||||
| Timestamp | Freshness guarantee | Every few hours |
|
||||
|
||||
---
|
||||
|
||||
## 2. Online Verification Flow
|
||||
|
||||
Client verification of attestations when network is available.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as StellaOps Client
|
||||
participant TUF as TUF Repository
|
||||
participant Rekor as Rekor Transparency Log
|
||||
participant Cache as Local Cache
|
||||
|
||||
Note over Client: Start verification
|
||||
|
||||
Client->>Cache: Check TUF metadata freshness
|
||||
alt Metadata stale
|
||||
Client->>TUF: Fetch timestamp.json
|
||||
TUF-->>Client: timestamp.json
|
||||
Client->>TUF: Fetch snapshot.json (if needed)
|
||||
TUF-->>Client: snapshot.json
|
||||
Client->>TUF: Fetch targets.json (if needed)
|
||||
TUF-->>Client: targets.json
|
||||
Client->>Cache: Update cached metadata
|
||||
end
|
||||
|
||||
Client->>Cache: Load Rekor public key
|
||||
Client->>Cache: Load service map
|
||||
|
||||
Note over Client: Resolve Rekor URL from service map
|
||||
|
||||
Client->>Rekor: GET /api/v2/log/entries/{uuid}/proof
|
||||
Rekor-->>Client: Inclusion proof + checkpoint
|
||||
|
||||
Note over Client: Verify:
|
||||
Note over Client: 1. Checkpoint signature (Rekor key)
|
||||
Note over Client: 2. Merkle inclusion proof
|
||||
Note over Client: 3. Entry matches attestation
|
||||
|
||||
Client-->>Client: Verification Result
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Offline Verification Flow
|
||||
|
||||
Client verification using sealed trust bundle (air-gapped).
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as StellaOps Client
|
||||
participant Bundle as Trust Bundle
|
||||
participant Tiles as Cached Tiles
|
||||
|
||||
Note over Client: Start offline verification
|
||||
|
||||
Client->>Bundle: Load TUF metadata
|
||||
Bundle-->>Client: root.json, targets.json, etc.
|
||||
|
||||
Client->>Bundle: Load Rekor public key
|
||||
Bundle-->>Client: rekor-key-v1.pub
|
||||
|
||||
Client->>Bundle: Load checkpoint
|
||||
Bundle-->>Client: Signed checkpoint
|
||||
|
||||
Note over Client: Verify checkpoint signature
|
||||
|
||||
Client->>Tiles: Load Merkle tiles for proof
|
||||
Tiles-->>Client: tile/data/..., tile/...
|
||||
|
||||
Note over Client: Reconstruct inclusion proof
|
||||
|
||||
Client->>Client: Verify Merkle path
|
||||
|
||||
Note over Client: No network calls required!
|
||||
|
||||
Client-->>Client: Verification Result
|
||||
```
|
||||
|
||||
### Trust Bundle Contents
|
||||
|
||||
```
|
||||
trust-bundle.tar.zst/
|
||||
├── manifest.json # Bundle metadata & checksums
|
||||
├── tuf/
|
||||
│ ├── root.json
|
||||
│ ├── targets.json
|
||||
│ ├── snapshot.json
|
||||
│ └── timestamp.json
|
||||
├── targets/
|
||||
│ ├── rekor-key-v1.pub
|
||||
│ ├── sigstore-services-v1.json
|
||||
│ └── fulcio-chain.pem
|
||||
└── tiles/ # Pre-fetched Merkle tiles
|
||||
├── checkpoint
|
||||
└── tile/
|
||||
├── 0/...
|
||||
├── 1/...
|
||||
└── data/...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Key Rotation Flow
|
||||
|
||||
Dual-key rotation with grace period.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> SingleKey: Initial State
|
||||
SingleKey --> DualKey: Add new key
|
||||
DualKey --> DualKey: Grace period<br/>(7-14 days)
|
||||
DualKey --> SingleKey: Remove old key
|
||||
SingleKey --> [*]
|
||||
|
||||
note right of SingleKey
|
||||
Only one key trusted
|
||||
All signatures use this key
|
||||
end note
|
||||
|
||||
note right of DualKey
|
||||
Both keys trusted
|
||||
Old attestations verify (old key)
|
||||
New attestations verify (new key)
|
||||
Clients sync new key
|
||||
end note
|
||||
```
|
||||
|
||||
### Detailed Rotation Timeline
|
||||
|
||||
```mermaid
|
||||
gantt
|
||||
title Key Rotation Timeline
|
||||
dateFormat YYYY-MM-DD
|
||||
|
||||
section TUF Admin
|
||||
Generate new key :done, gen, 2026-01-01, 1d
|
||||
Add to TUF repository :done, add, after gen, 1d
|
||||
Sign & publish metadata :done, pub, after add, 1d
|
||||
|
||||
section Grace Period
|
||||
Dual-key active :active, grace, after pub, 14d
|
||||
Monitor client sync :monitor, after pub, 14d
|
||||
|
||||
section Completion
|
||||
Remove old key :remove, after grace, 1d
|
||||
Sign & publish final :final, after remove, 1d
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Failover Flow
|
||||
|
||||
Circuit breaker and mirror failover during primary outage.
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Closed: Normal operation
|
||||
|
||||
state "Circuit Breaker" as CB {
|
||||
Closed --> Open: Failures > threshold
|
||||
Open --> HalfOpen: After timeout
|
||||
HalfOpen --> Closed: Success
|
||||
HalfOpen --> Open: Failure
|
||||
}
|
||||
|
||||
state "Request Routing" as Routing {
|
||||
Primary: Primary Rekor
|
||||
Mirror: Mirror Rekor
|
||||
}
|
||||
|
||||
Closed --> Primary: Route to primary
|
||||
Open --> Mirror: Failover to mirror
|
||||
HalfOpen --> Primary: Probe primary
|
||||
|
||||
note right of Open
|
||||
Primary unavailable
|
||||
Use mirror if configured
|
||||
Cache tiles locally
|
||||
end note
|
||||
```
|
||||
|
||||
### Failover Decision Tree
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
START([Request]) --> CB{Circuit<br/>Breaker<br/>State?}
|
||||
|
||||
CB -->|Closed| PRIMARY[Try Primary]
|
||||
CB -->|Open| MIRROR_CHECK{Mirror<br/>Enabled?}
|
||||
CB -->|HalfOpen| PROBE[Probe Primary]
|
||||
|
||||
PRIMARY -->|Success| SUCCESS([Return Result])
|
||||
PRIMARY -->|Failure| RECORD[Record Failure]
|
||||
RECORD --> THRESHOLD{Threshold<br/>Exceeded?}
|
||||
THRESHOLD -->|Yes| OPEN_CB[Open Circuit]
|
||||
THRESHOLD -->|No| FAIL([Return Error])
|
||||
|
||||
OPEN_CB --> MIRROR_CHECK
|
||||
|
||||
MIRROR_CHECK -->|Yes| MIRROR[Try Mirror]
|
||||
MIRROR_CHECK -->|No| CACHE{Cached<br/>Data?}
|
||||
|
||||
MIRROR -->|Success| SUCCESS
|
||||
MIRROR -->|Failure| CACHE
|
||||
|
||||
CACHE -->|Yes| CACHED([Return Cached])
|
||||
CACHE -->|No| FAIL
|
||||
|
||||
PROBE -->|Success| CLOSE_CB[Close Circuit]
|
||||
PROBE -->|Failure| OPEN_CB
|
||||
|
||||
CLOSE_CB --> SUCCESS
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Component Architecture
|
||||
|
||||
Full system component view.
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Client Layer"
|
||||
CLI[stella CLI]
|
||||
SDK[StellaOps SDK]
|
||||
end
|
||||
|
||||
subgraph "Trust Layer"
|
||||
TUF_CLIENT[TUF Client]
|
||||
CACHE[(Local Cache)]
|
||||
CB[Circuit Breaker]
|
||||
end
|
||||
|
||||
subgraph "Service Layer"
|
||||
TUF_SERVER[TUF Server]
|
||||
REKOR_PRIMARY[Rekor Primary]
|
||||
REKOR_MIRROR[Rekor Mirror / Tile Proxy]
|
||||
end
|
||||
|
||||
subgraph "Storage Layer"
|
||||
TUF_STORE[(TUF Metadata)]
|
||||
LOG_STORE[(Transparency Log)]
|
||||
TILE_STORE[(Tile Storage)]
|
||||
end
|
||||
|
||||
CLI --> TUF_CLIENT
|
||||
SDK --> TUF_CLIENT
|
||||
|
||||
TUF_CLIENT --> CACHE
|
||||
TUF_CLIENT --> CB
|
||||
CB --> REKOR_PRIMARY
|
||||
CB --> REKOR_MIRROR
|
||||
|
||||
TUF_CLIENT --> TUF_SERVER
|
||||
TUF_SERVER --> TUF_STORE
|
||||
|
||||
REKOR_PRIMARY --> LOG_STORE
|
||||
REKOR_MIRROR --> TILE_STORE
|
||||
|
||||
style CB fill:#ff9999
|
||||
style CACHE fill:#99ff99
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Data Flow Summary
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph "Bootstrap"
|
||||
A[Initialize TUF] --> B[Fetch Root]
|
||||
B --> C[Fetch Metadata Chain]
|
||||
C --> D[Cache Targets]
|
||||
end
|
||||
|
||||
subgraph "Attestation"
|
||||
E[Create Attestation] --> F[Sign DSSE]
|
||||
F --> G[Submit to Rekor]
|
||||
G --> H[Store Proof]
|
||||
end
|
||||
|
||||
subgraph "Verification"
|
||||
I[Load Attestation] --> J[Check TUF Freshness]
|
||||
J --> K[Fetch Inclusion Proof]
|
||||
K --> L[Verify Merkle Path]
|
||||
L --> M[Check Checkpoint Sig]
|
||||
M --> N[Return Result]
|
||||
end
|
||||
|
||||
D --> E
|
||||
H --> I
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [TUF Integration Guide](../tuf-integration.md)
|
||||
- [Rekor Verification Design](../rekor-verification-design.md)
|
||||
- [Bootstrap Guide](../../../operations/bootstrap-guide.md)
|
||||
- [Key Rotation Runbook](../../../operations/key-rotation-runbook.md)
|
||||
- [Disaster Recovery](../../../operations/disaster-recovery.md)
|
||||
262
docs/modules/attestor/tile-proxy-design.md
Normal file
262
docs/modules/attestor/tile-proxy-design.md
Normal file
@@ -0,0 +1,262 @@
|
||||
# Tile-Proxy Service Design
|
||||
|
||||
## Overview
|
||||
|
||||
The Tile-Proxy service acts as an intermediary between StellaOps clients and upstream Rekor transparency log APIs. It provides centralized tile caching, request coalescing, and offline support for air-gapped environments.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ CI/CD Agents │────►│ Tile Proxy │────►│ Rekor API │
|
||||
│ (StellaOps) │ │ (StellaOps) │ │ (Upstream) │
|
||||
└─────────────────┘ └────────┬────────┘ └─────────────────┘
|
||||
│
|
||||
┌───────────────────────┼───────────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Tile Cache │ │ TUF Metadata │ │ Checkpoint │
|
||||
│ (CAS Store) │ │ (TrustRepo) │ │ Cache │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
## Core Responsibilities
|
||||
|
||||
1. **Tile Proxying**: Forward tile requests to upstream Rekor, caching responses locally
|
||||
2. **Content-Addressed Storage**: Store tiles by hash for deduplication and immutability
|
||||
3. **TUF Integration**: Optionally validate metadata using TUF trust anchors
|
||||
4. **Request Coalescing**: Deduplicate concurrent requests for the same tile
|
||||
5. **Checkpoint Caching**: Cache and serve recent checkpoints
|
||||
6. **Offline Mode**: Serve from cache when upstream is unavailable
|
||||
|
||||
## API Surface
|
||||
|
||||
### Proxy Endpoints (Passthrough)
|
||||
|
||||
| Endpoint | Description |
|
||||
|----------|-------------|
|
||||
| `GET /tile/{level}/{index}` | Proxy tile request (cache-through) |
|
||||
| `GET /tile/{level}/{index}.p/{partialWidth}` | Proxy partial tile |
|
||||
| `GET /checkpoint` | Proxy checkpoint request |
|
||||
| `GET /api/v1/log/entries/{uuid}` | Proxy entry lookup |
|
||||
|
||||
### Admin Endpoints
|
||||
|
||||
| Endpoint | Description |
|
||||
|----------|-------------|
|
||||
| `GET /_admin/cache/stats` | Cache statistics (hits, misses, size) |
|
||||
| `POST /_admin/cache/sync` | Trigger manual sync job |
|
||||
| `DELETE /_admin/cache/prune` | Prune old tiles |
|
||||
| `GET /_admin/health` | Health check |
|
||||
| `GET /_admin/ready` | Readiness check |
|
||||
|
||||
## Caching Strategy
|
||||
|
||||
### Content-Addressed Tile Storage
|
||||
|
||||
Tiles are stored using content-addressed paths based on SHA-256 hash:
|
||||
|
||||
```
|
||||
{cache_root}/
|
||||
├── tiles/
|
||||
│ ├── {origin_hash}/
|
||||
│ │ ├── {level}/
|
||||
│ │ │ ├── {index}.tile
|
||||
│ │ │ └── {index}.meta.json
|
||||
│ │ └── checkpoints/
|
||||
│ │ └── {tree_size}.checkpoint
|
||||
│ └── ...
|
||||
└── metadata/
|
||||
└── cache_stats.json
|
||||
```
|
||||
|
||||
### Tile Metadata
|
||||
|
||||
Each tile has associated metadata:
|
||||
|
||||
```json
|
||||
{
|
||||
"cachedAt": "2026-01-25T10:00:00Z",
|
||||
"treeSize": 1050000,
|
||||
"isPartial": false,
|
||||
"contentHash": "sha256:abc123...",
|
||||
"upstreamUrl": "https://rekor.sigstore.dev"
|
||||
}
|
||||
```
|
||||
|
||||
### Eviction Policy
|
||||
|
||||
1. **LRU by Access Time**: Least recently accessed tiles evicted first
|
||||
2. **Max Size Limit**: Configurable maximum cache size
|
||||
3. **TTL Override**: Force re-fetch after configurable time (for checkpoints)
|
||||
4. **Immutability Preservation**: Full tiles (width=256) never evicted unless explicitly pruned
|
||||
|
||||
## Request Coalescing
|
||||
|
||||
Concurrent requests for the same tile are coalesced:
|
||||
|
||||
```csharp
|
||||
// Pseudo-code for request coalescing
|
||||
var key = $"{origin}/{level}/{index}";
|
||||
if (_inflightRequests.TryGetValue(key, out var existing))
|
||||
{
|
||||
return await existing; // Wait for in-flight request
|
||||
}
|
||||
|
||||
var tcs = new TaskCompletionSource<byte[]>();
|
||||
_inflightRequests[key] = tcs.Task;
|
||||
try
|
||||
{
|
||||
var tile = await FetchFromUpstream(origin, level, index);
|
||||
tcs.SetResult(tile);
|
||||
return tile;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_inflightRequests.Remove(key);
|
||||
}
|
||||
```
|
||||
|
||||
## TUF Integration Point
|
||||
|
||||
When `TufValidationEnabled` is true:
|
||||
|
||||
1. Load service map from TUF to discover Rekor URL
|
||||
2. Validate Rekor public key from TUF targets
|
||||
3. Verify checkpoint signatures using TUF-loaded keys
|
||||
4. Reject tiles if checkpoint signature invalid
|
||||
|
||||
## Upstream Failover
|
||||
|
||||
Support multiple upstream sources with failover:
|
||||
|
||||
```yaml
|
||||
tile_proxy:
|
||||
upstreams:
|
||||
- url: https://rekor.sigstore.dev
|
||||
priority: 1
|
||||
timeout: 30s
|
||||
- url: https://rekor-mirror.internal
|
||||
priority: 2
|
||||
timeout: 10s
|
||||
```
|
||||
|
||||
Failover behavior:
|
||||
1. Try primary upstream first
|
||||
2. On timeout/error, try next upstream
|
||||
3. Cache successful source for subsequent requests
|
||||
4. Reset failover state on explicit refresh
|
||||
|
||||
## Deployment Model
|
||||
|
||||
### Standalone Service
|
||||
|
||||
Run as dedicated service with persistent volume:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
tile-proxy:
|
||||
image: stellaops/tile-proxy:latest
|
||||
ports:
|
||||
- "8090:8080"
|
||||
volumes:
|
||||
- tile-cache:/var/cache/stellaops/tiles
|
||||
- tuf-cache:/var/cache/stellaops/tuf
|
||||
environment:
|
||||
- TILE_PROXY__UPSTREAM_URL=https://rekor.sigstore.dev
|
||||
- TILE_PROXY__TUF_URL=https://trust.stella-ops.org/tuf/
|
||||
```
|
||||
|
||||
### Sidecar Mode
|
||||
|
||||
Run alongside attestor service:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
attestor:
|
||||
image: stellaops/attestor:latest
|
||||
environment:
|
||||
- ATTESTOR__REKOR_URL=http://localhost:8090 # Use sidecar
|
||||
|
||||
tile-proxy:
|
||||
image: stellaops/tile-proxy:latest
|
||||
network_mode: "service:attestor"
|
||||
```
|
||||
|
||||
## Metrics
|
||||
|
||||
Prometheus metrics exposed at `/_admin/metrics`:
|
||||
|
||||
| Metric | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| `tile_proxy_cache_hits_total` | Counter | Total cache hits |
|
||||
| `tile_proxy_cache_misses_total` | Counter | Total cache misses |
|
||||
| `tile_proxy_cache_size_bytes` | Gauge | Current cache size |
|
||||
| `tile_proxy_upstream_requests_total` | Counter | Upstream requests by status |
|
||||
| `tile_proxy_request_duration_seconds` | Histogram | Request latency |
|
||||
| `tile_proxy_sync_last_success_timestamp` | Gauge | Last successful sync time |
|
||||
|
||||
## Configuration
|
||||
|
||||
```yaml
|
||||
tile_proxy:
|
||||
# Upstream Rekor configuration
|
||||
upstream_url: https://rekor.sigstore.dev
|
||||
tile_base_url: https://rekor.sigstore.dev/tile/
|
||||
|
||||
# TUF integration (optional)
|
||||
tuf:
|
||||
enabled: true
|
||||
url: https://trust.stella-ops.org/tuf/
|
||||
validate_checkpoint_signature: true
|
||||
|
||||
# Cache configuration
|
||||
cache:
|
||||
base_path: /var/cache/stellaops/tiles
|
||||
max_size_gb: 10
|
||||
eviction_policy: lru
|
||||
checkpoint_ttl_minutes: 5
|
||||
|
||||
# Sync job configuration
|
||||
sync:
|
||||
enabled: true
|
||||
schedule: "0 */6 * * *"
|
||||
depth: 10000
|
||||
|
||||
# Request handling
|
||||
coalescing:
|
||||
enabled: true
|
||||
max_wait_ms: 5000
|
||||
|
||||
# Failover
|
||||
failover:
|
||||
enabled: true
|
||||
retry_count: 2
|
||||
retry_delay_ms: 1000
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **No Authentication by Default**: Designed for internal network use
|
||||
2. **Optional mTLS**: Can enable client certificate validation
|
||||
3. **Rate Limiting**: Optional rate limiting per client IP
|
||||
4. **Audit Logging**: Log all cache operations for compliance
|
||||
5. **Immutable Tiles**: Full tiles are never modified after caching
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Scenario | Behavior |
|
||||
|----------|----------|
|
||||
| Upstream unavailable | Serve from cache if available; 503 otherwise |
|
||||
| Invalid tile data | Reject, don't cache, log error |
|
||||
| Cache full | Evict LRU tiles, continue serving |
|
||||
| TUF validation fails | Reject request, return 502 |
|
||||
| Checkpoint stale | Refresh from upstream, warn in logs |
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
1. **Tile Prefetching**: Prefetch tiles for known verification patterns
|
||||
2. **Multi-Log Support**: Support multiple transparency logs
|
||||
3. **Replication**: Sync cache between proxy instances
|
||||
4. **Compression**: Optional tile compression for storage
|
||||
287
docs/modules/attestor/tuf-integration.md
Normal file
287
docs/modules/attestor/tuf-integration.md
Normal file
@@ -0,0 +1,287 @@
|
||||
# TUF Integration Guide
|
||||
|
||||
This guide explains how StellaOps uses The Update Framework (TUF) for secure trust
|
||||
distribution and how to configure TUF-based trust management.
|
||||
|
||||
## Overview
|
||||
|
||||
TUF provides a secure method for distributing and updating trust anchors (public keys,
|
||||
service endpoints) without requiring client reconfiguration. StellaOps uses TUF to:
|
||||
|
||||
- Distribute Rekor public keys for checkpoint verification
|
||||
- Distribute Fulcio certificate chains for keyless signing
|
||||
- Provide service endpoint discovery (Rekor, Fulcio URLs)
|
||||
- Enable secure key rotation with grace periods
|
||||
- Support offline verification with bundled trust state
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ TUF Trust Hierarchy │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────┐ │
|
||||
│ │ Root │ ← Offline, rotates rarely (yearly) │
|
||||
│ │ Key │ │
|
||||
│ └────┬────┘ │
|
||||
│ │ │
|
||||
│ ┌────┴────────────────────────────┐ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ Snapshot │ │Timestamp │ │ Targets │ │
|
||||
│ │ Key │ │ Key │ │ Key │ │
|
||||
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
|
||||
│ │ │ │ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ snapshot.json timestamp.json targets.json │
|
||||
│ │ │ │
|
||||
│ │ ├── rekor-key-v1.pub │
|
||||
│ │ ├── rekor-key-v2.pub │
|
||||
│ │ ├── fulcio-chain.pem │
|
||||
│ │ └── sigstore-services-v1.json │
|
||||
│ │ │
|
||||
│ └── Refreshed frequently (daily) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## TUF Roles
|
||||
|
||||
### Root
|
||||
- Signs the root metadata containing all role keys
|
||||
- Highest trust level, rotates rarely
|
||||
- Should be kept offline in secure storage (HSM, air-gapped system)
|
||||
- Used only for initial setup and key rotation ceremonies
|
||||
|
||||
### Timestamp
|
||||
- Signs timestamp metadata indicating freshness
|
||||
- Must be refreshed frequently (default: daily)
|
||||
- Clients reject metadata older than expiration
|
||||
- Can be automated with short-lived credentials
|
||||
|
||||
### Snapshot
|
||||
- Signs snapshot metadata listing current target versions
|
||||
- Updated when targets change
|
||||
- Prevents rollback attacks
|
||||
|
||||
### Targets
|
||||
- Signs metadata for actual target files
|
||||
- Lists hashes and sizes for verification
|
||||
- Supports delegations for large repositories
|
||||
|
||||
## Configuration
|
||||
|
||||
### Attestor Configuration
|
||||
|
||||
```yaml
|
||||
attestor:
|
||||
trust_repo:
|
||||
enabled: true
|
||||
tuf_url: https://trust.yourcompany.com/tuf/
|
||||
refresh_interval_minutes: 60
|
||||
freshness_threshold_days: 7
|
||||
offline_mode: false
|
||||
local_cache_path: /var/lib/stellaops/tuf-cache
|
||||
service_map_target: sigstore-services-v1
|
||||
rekor_key_targets:
|
||||
- rekor-key-v1
|
||||
- rekor-key-v2
|
||||
```
|
||||
|
||||
### Configuration Options
|
||||
|
||||
| Option | Description | Default |
|
||||
|--------|-------------|---------|
|
||||
| `enabled` | Enable TUF-based trust distribution | `false` |
|
||||
| `tuf_url` | URL to TUF repository root | Required |
|
||||
| `refresh_interval_minutes` | How often to check for updates | `60` |
|
||||
| `freshness_threshold_days` | Max age before rejecting metadata | `7` |
|
||||
| `offline_mode` | Use bundled metadata only | `false` |
|
||||
| `local_cache_path` | Local metadata cache directory | OS-specific |
|
||||
| `service_map_target` | TUF target name for service map | `sigstore-services-v1` |
|
||||
| `rekor_key_targets` | TUF target names for Rekor keys | `["rekor-key-v1"]` |
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `STELLA_TUF_ROOT_URL` | Override TUF repository URL |
|
||||
| `STELLA_SIGSTORE_SERVICE_MAP` | Path to local service map override |
|
||||
| `STELLA_TUF_OFFLINE_MODE` | Force offline mode (`true`/`false`) |
|
||||
|
||||
## CLI Usage
|
||||
|
||||
### Initialize Trust
|
||||
|
||||
```bash
|
||||
# Initialize with a TUF repository
|
||||
stella trust init \
|
||||
--tuf-url https://trust.yourcompany.com/tuf/ \
|
||||
--service-map sigstore-services-v1 \
|
||||
--pin rekor-key-v1 rekor-key-v2
|
||||
|
||||
# Initialize in offline mode with bundled metadata
|
||||
stella trust init \
|
||||
--tuf-url file:///path/to/bundled-trust/ \
|
||||
--offline
|
||||
```
|
||||
|
||||
### Sync Metadata
|
||||
|
||||
```bash
|
||||
# Refresh TUF metadata
|
||||
stella trust sync
|
||||
|
||||
# Force refresh even if fresh
|
||||
stella trust sync --force
|
||||
```
|
||||
|
||||
### Check Status
|
||||
|
||||
```bash
|
||||
# Show current trust state
|
||||
stella trust status
|
||||
|
||||
# Show with key details
|
||||
stella trust status --show-keys --show-endpoints
|
||||
```
|
||||
|
||||
### Export for Offline Use
|
||||
|
||||
```bash
|
||||
# Export trust state
|
||||
stella trust export --out ./trust-bundle/
|
||||
|
||||
# Create sealed snapshot with tiles
|
||||
stella trust snapshot export \
|
||||
--out ./snapshots/2026-01-25.tar.zst \
|
||||
--depth 10000
|
||||
```
|
||||
|
||||
### Import Offline Bundle
|
||||
|
||||
```bash
|
||||
# Import trust bundle
|
||||
stella trust import ./snapshots/2026-01-25.tar.zst \
|
||||
--verify-manifest \
|
||||
--reject-if-stale 7d
|
||||
```
|
||||
|
||||
## Service Map
|
||||
|
||||
The service map (`sigstore-services-v1.json`) contains endpoint URLs for Sigstore
|
||||
services. This enables endpoint changes without client reconfiguration.
|
||||
|
||||
### Schema
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"rekor": {
|
||||
"url": "https://rekor.sigstore.dev",
|
||||
"log_id": "c0d23d6ad406973f9559f3ba2d1ca01f84147d8ffc5b8445c224f98b9591801d",
|
||||
"public_key_target": "rekor-key-v1"
|
||||
},
|
||||
"fulcio": {
|
||||
"url": "https://fulcio.sigstore.dev",
|
||||
"root_cert_target": "fulcio-chain.pem"
|
||||
},
|
||||
"overrides": {
|
||||
"staging": {
|
||||
"rekor_url": "https://rekor.sigstage.dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Site-Local Overrides
|
||||
|
||||
Organizations can define environment-specific overrides:
|
||||
|
||||
```yaml
|
||||
attestor:
|
||||
trust_repo:
|
||||
environment: staging # Use staging overrides from service map
|
||||
```
|
||||
|
||||
## Key Rotation
|
||||
|
||||
TUF supports secure key rotation with grace periods:
|
||||
|
||||
1. **Add new key**: Publish new key while keeping old key active
|
||||
2. **Grace period**: Clients sync and receive both keys
|
||||
3. **Verify**: Ensure all clients have new key
|
||||
4. **Revoke old key**: Remove old key from active set
|
||||
|
||||
See [Key Rotation Runbook](../../operations/key-rotation-runbook.md) for detailed procedures.
|
||||
|
||||
## Offline Mode
|
||||
|
||||
For air-gapped environments, StellaOps can operate with bundled TUF metadata:
|
||||
|
||||
1. Export trust state on connected system:
|
||||
```bash
|
||||
stella trust snapshot export --out ./bundle.tar.zst
|
||||
```
|
||||
|
||||
2. Transfer bundle to air-gapped system
|
||||
|
||||
3. Import on air-gapped system:
|
||||
```bash
|
||||
stella trust import ./bundle.tar.zst --offline
|
||||
```
|
||||
|
||||
4. Verify attestations using bundled trust:
|
||||
```bash
|
||||
stella attest verify ./attestation.json --offline
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "TUF metadata expired"
|
||||
|
||||
The timestamp hasn't been refreshed. On the TUF repository:
|
||||
```bash
|
||||
./scripts/update-timestamp.sh
|
||||
```
|
||||
|
||||
### "Unknown target"
|
||||
|
||||
The requested target doesn't exist in the repository:
|
||||
```bash
|
||||
./scripts/add-target.sh /path/to/target target-name
|
||||
```
|
||||
|
||||
### "Signature verification failed"
|
||||
|
||||
Keys may have rotated. Force a sync:
|
||||
```bash
|
||||
stella trust sync --force
|
||||
```
|
||||
|
||||
### "Service map not found"
|
||||
|
||||
Ensure the service map target name matches configuration:
|
||||
```bash
|
||||
stella trust status # Check service_map_target value
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Root Key Security**: Keep root key offline. Only use for initial setup and rotations.
|
||||
|
||||
2. **Timestamp Automation**: Automate timestamp updates but use short-lived credentials.
|
||||
|
||||
3. **Monitoring**: Monitor for failed TUF fetches - may indicate MITM or repository issues.
|
||||
|
||||
4. **Rollback Protection**: TUF prevents rollback attacks through version tracking.
|
||||
|
||||
5. **Freshness**: Configure appropriate freshness thresholds for your security requirements.
|
||||
|
||||
## References
|
||||
|
||||
- [TUF Specification](https://theupdateframework.github.io/specification/latest/)
|
||||
- [Sigstore Trust Root](https://github.com/sigstore/root-signing)
|
||||
- [StellaOps Trust Repository Template](../../../devops/trust-repo-template/)
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"eventId": "d4e5f6a7-89ab-cdef-0123-456789abcdef",
|
||||
"kind": "attestor.logged",
|
||||
"version": "1",
|
||||
"tenant": "tenant-01",
|
||||
"ts": "2025-12-24T13:00:00+00:00",
|
||||
"actor": "attestor-service",
|
||||
"payload": {
|
||||
"attestationId": "attest-001-20251224",
|
||||
"imageDigest": "sha256:abc123def456789012345678901234567890123456789012345678901234abcd",
|
||||
"imageName": "registry.example.com/app:v1.0.0",
|
||||
"predicateType": "https://slsa.dev/provenance/v1",
|
||||
"logIndex": 12345,
|
||||
"links": {
|
||||
"attestation": "https://stellaops.example.com/attestations/attest-001-20251224",
|
||||
"rekor": "https://rekor.sigstore.dev/api/v1/log/entries?logIndex=12345"
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"category": "attestor",
|
||||
"logProvider": "rekor"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"eventId": "b2c3d4e5-6789-abcd-ef01-23456789abcd",
|
||||
"kind": "scanner.report.ready",
|
||||
"version": "1",
|
||||
"tenant": "tenant-01",
|
||||
"ts": "2025-12-24T11:00:00+00:00",
|
||||
"actor": "scanner-worker",
|
||||
"payload": {
|
||||
"reportId": "report-001-20251224",
|
||||
"scanId": "scan-001-20251224",
|
||||
"imageDigest": "sha256:abc123def456789012345678901234567890123456789012345678901234abcd",
|
||||
"imageName": "registry.example.com/app:v1.0.0",
|
||||
"format": "cyclonedx",
|
||||
"size": 524288,
|
||||
"links": {
|
||||
"report": "https://stellaops.example.com/reports/report-001-20251224",
|
||||
"download": "https://stellaops.example.com/reports/report-001-20251224/download"
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"category": "scanner",
|
||||
"reportFormat": "cyclonedx-1.5"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"eventId": "a1b2c3d4-5678-9abc-def0-123456789abc",
|
||||
"kind": "scanner.scan.completed",
|
||||
"version": "1",
|
||||
"tenant": "tenant-01",
|
||||
"ts": "2025-12-24T10:30:00+00:00",
|
||||
"actor": "scanner-worker",
|
||||
"payload": {
|
||||
"scanId": "scan-001-20251224",
|
||||
"imageDigest": "sha256:abc123def456789012345678901234567890123456789012345678901234abcd",
|
||||
"imageName": "registry.example.com/app:v1.0.0",
|
||||
"verdict": "pass",
|
||||
"findingsCount": 7,
|
||||
"vulnerabilities": {
|
||||
"critical": 0,
|
||||
"high": 0,
|
||||
"medium": 2,
|
||||
"low": 5
|
||||
},
|
||||
"scanDurationMs": 15230,
|
||||
"links": {
|
||||
"findings": "https://stellaops.example.com/scans/scan-001-20251224/findings",
|
||||
"sbom": "https://stellaops.example.com/scans/scan-001-20251224/sbom"
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"category": "scanner",
|
||||
"environment": "production"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"eventId": "c3d4e5f6-789a-bcde-f012-3456789abcde",
|
||||
"kind": "scheduler.rescan.delta",
|
||||
"version": "1",
|
||||
"tenant": "tenant-01",
|
||||
"ts": "2025-12-24T12:00:00+00:00",
|
||||
"actor": "scheduler-service",
|
||||
"payload": {
|
||||
"scheduleId": "schedule-daily-rescan",
|
||||
"deltaId": "delta-20251224-1200",
|
||||
"imagesAffected": 15,
|
||||
"newVulnerabilities": 3,
|
||||
"resolvedVulnerabilities": 2,
|
||||
"links": {
|
||||
"schedule": "https://stellaops.example.com/schedules/schedule-daily-rescan",
|
||||
"delta": "https://stellaops.example.com/deltas/delta-20251224-1200"
|
||||
}
|
||||
},
|
||||
"attributes": {
|
||||
"category": "scheduler",
|
||||
"scheduleType": "daily"
|
||||
}
|
||||
}
|
||||
42
docs/notifications/operations/alerts/notify-slo-alerts.yaml
Normal file
42
docs/notifications/operations/alerts/notify-slo-alerts.yaml
Normal file
@@ -0,0 +1,42 @@
|
||||
# Notify SLO Alerts
|
||||
# Prometheus alerting rules for the notification service
|
||||
|
||||
groups:
|
||||
- name: notify-slo
|
||||
rules:
|
||||
- alert: NotifyDeliverySuccessSLO
|
||||
expr: |
|
||||
(
|
||||
sum(rate(notify_delivery_success_total[5m])) /
|
||||
sum(rate(notify_delivery_total[5m]))
|
||||
) < 0.99
|
||||
for: 5m
|
||||
labels:
|
||||
severity: critical
|
||||
service: notify
|
||||
annotations:
|
||||
summary: "Notification delivery success rate below SLO"
|
||||
description: "Current success rate: {{ $value | humanizePercentage }}"
|
||||
|
||||
- alert: NotifyBacklogDepth
|
||||
expr: notify_backlog_depth > 10000
|
||||
for: 10m
|
||||
labels:
|
||||
severity: warning
|
||||
service: notify
|
||||
annotations:
|
||||
summary: "Notification backlog depth high"
|
||||
description: "Current backlog: {{ $value }} notifications"
|
||||
|
||||
- alert: NotifyLatencyP99
|
||||
expr: |
|
||||
histogram_quantile(0.99,
|
||||
sum(rate(notify_delivery_duration_seconds_bucket[5m])) by (le)
|
||||
) > 5
|
||||
for: 5m
|
||||
labels:
|
||||
severity: warning
|
||||
service: notify
|
||||
annotations:
|
||||
summary: "Notification delivery P99 latency high"
|
||||
description: "P99 latency: {{ $value | humanizeDuration }}"
|
||||
32
docs/notifications/operations/quotas.md
Normal file
32
docs/notifications/operations/quotas.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Notification Quotas
|
||||
|
||||
This document describes the quota system for notification delivery.
|
||||
|
||||
## Overview
|
||||
|
||||
Quotas ensure fair usage of the notification system across tenants.
|
||||
|
||||
## Quota Types
|
||||
|
||||
### Daily Limits
|
||||
- Maximum notifications per day per tenant
|
||||
- Maximum notifications per channel per day
|
||||
|
||||
### Rate Limits
|
||||
- Maximum notifications per minute
|
||||
- Maximum notifications per second per channel
|
||||
|
||||
### Size Limits
|
||||
- Maximum payload size
|
||||
- Maximum attachment count
|
||||
|
||||
## Quota Enforcement
|
||||
|
||||
Quota violations result in:
|
||||
1. Notification is queued for later delivery
|
||||
2. Tenant is notified of quota exceeded
|
||||
3. Admin alert is triggered if threshold is reached
|
||||
|
||||
## Configuration
|
||||
|
||||
Quotas are configured per tenant and can be overridden by administrators.
|
||||
38
docs/notifications/operations/retries.md
Normal file
38
docs/notifications/operations/retries.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# Notification Retries
|
||||
|
||||
This document describes the retry mechanism for failed notification deliveries.
|
||||
|
||||
## Overview
|
||||
|
||||
The retry system ensures reliable notification delivery even when temporary failures occur.
|
||||
|
||||
## Retry Strategy
|
||||
|
||||
### Exponential Backoff
|
||||
- Initial delay: 5 seconds
|
||||
- Maximum delay: 1 hour
|
||||
- Backoff multiplier: 2x
|
||||
|
||||
### Retry Limits
|
||||
- Maximum attempts: 10
|
||||
- Maximum retry duration: 24 hours
|
||||
|
||||
### Retry Conditions
|
||||
- Network errors: Always retry
|
||||
- HTTP 5xx errors: Always retry
|
||||
- HTTP 429 (rate limit): Retry with Retry-After header
|
||||
- HTTP 4xx errors: Do not retry (permanent failure)
|
||||
|
||||
## Dead Letter Queue
|
||||
|
||||
Notifications that exceed retry limits are moved to the dead letter queue for:
|
||||
- Manual inspection
|
||||
- Automatic alerting
|
||||
- Scheduled reprocessing
|
||||
|
||||
## Monitoring
|
||||
|
||||
Retry metrics are exposed for:
|
||||
- Retry count per notification
|
||||
- Success rate after retries
|
||||
- Average retry duration
|
||||
27
docs/notifications/schemas/notify-schemas-catalog.json
Normal file
27
docs/notifications/schemas/notify-schemas-catalog.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "https://docs.stella-ops.org/notifications/schemas/notify-schemas-catalog.json",
|
||||
"title": "Notify Schemas Catalog",
|
||||
"description": "Catalog of all notification schemas",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string",
|
||||
"const": "1.0.0"
|
||||
},
|
||||
"schemas": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": { "type": "string" },
|
||||
"version": { "type": "string" },
|
||||
"description": { "type": "string" },
|
||||
"path": { "type": "string" }
|
||||
},
|
||||
"required": ["name", "version", "path"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["version", "schemas"]
|
||||
}
|
||||
28
docs/notifications/security/redaction-catalog.md
Normal file
28
docs/notifications/security/redaction-catalog.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Redaction Catalog
|
||||
|
||||
This document catalogs the redaction rules applied to notification payloads.
|
||||
|
||||
## Overview
|
||||
|
||||
The redaction catalog ensures that sensitive information is not exposed in notifications.
|
||||
|
||||
## Redaction Rules
|
||||
|
||||
### Personal Identifiable Information (PII)
|
||||
- Email addresses are partially redacted
|
||||
- IP addresses are anonymized
|
||||
- User names are replaced with user IDs
|
||||
|
||||
### Credentials
|
||||
- API keys are fully redacted
|
||||
- Passwords are never included
|
||||
- Tokens are truncated to first/last 4 characters
|
||||
|
||||
### Internal Data
|
||||
- Internal URLs are replaced with public equivalents
|
||||
- Database IDs are not exposed
|
||||
- Stack traces are summarized
|
||||
|
||||
## Configuration
|
||||
|
||||
Redaction rules can be customized per tenant and notification channel.
|
||||
19
docs/notifications/security/tenant-approvals.md
Normal file
19
docs/notifications/security/tenant-approvals.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Tenant Approvals
|
||||
|
||||
This document describes the tenant approval process for notification delivery.
|
||||
|
||||
## Overview
|
||||
|
||||
Tenant approvals ensure that notifications are only sent to approved tenants with proper configuration.
|
||||
|
||||
## Approval Process
|
||||
|
||||
1. Tenant submits a request for notification access
|
||||
2. Admin reviews the request and approves/denies
|
||||
3. Approved tenants can configure notification channels
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- All approval decisions are logged for audit purposes
|
||||
- Approvals can be revoked at any time
|
||||
- Cross-tenant notifications are blocked by default
|
||||
22
docs/notifications/security/webhook-ack-hardening.md
Normal file
22
docs/notifications/security/webhook-ack-hardening.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Webhook Acknowledgment Hardening
|
||||
|
||||
This document describes the security measures for webhook acknowledgment validation.
|
||||
|
||||
## Overview
|
||||
|
||||
Webhook acknowledgment hardening ensures that webhook deliveries are properly verified and acknowledged.
|
||||
|
||||
## Security Measures
|
||||
|
||||
- HMAC signature verification for all webhook payloads
|
||||
- Timeout handling for slow webhook endpoints
|
||||
- Retry logic with exponential backoff
|
||||
- Dead letter queue for failed deliveries
|
||||
|
||||
## Configuration
|
||||
|
||||
Webhook endpoints must be configured with:
|
||||
- Secret key for HMAC signing
|
||||
- Signature header name
|
||||
- Timeout duration
|
||||
- Maximum retry attempts
|
||||
4
docs/notifications/simulations/index.ndjson
Normal file
4
docs/notifications/simulations/index.ndjson
Normal file
@@ -0,0 +1,4 @@
|
||||
{"simulation_id": "sim-001", "name": "High Volume Burst", "description": "Simulates a burst of 10000 notifications in 1 minute", "tenant": "test-tenant", "status": "ready"}
|
||||
{"simulation_id": "sim-002", "name": "Rate Limit Test", "description": "Simulates hitting rate limits across all channels", "tenant": "test-tenant", "status": "ready"}
|
||||
{"simulation_id": "sim-003", "name": "Retry Storm", "description": "Simulates webhook endpoints returning 500 errors causing retries", "tenant": "test-tenant", "status": "ready"}
|
||||
{"simulation_id": "sim-004", "name": "Multi-Tenant Isolation", "description": "Validates tenant isolation with concurrent notifications", "tenant": "test-tenant", "status": "ready"}
|
||||
248
docs/operations/bootstrap-guide.md
Normal file
248
docs/operations/bootstrap-guide.md
Normal file
@@ -0,0 +1,248 @@
|
||||
# StellaOps Trust Bootstrap Guide
|
||||
|
||||
> Sprint: SPRINT_20260125_003 - WORKFLOW-001
|
||||
> Last updated: 2026-01-25
|
||||
|
||||
## Overview
|
||||
|
||||
This guide covers the initial trust setup for a new StellaOps deployment. Trust
|
||||
bootstrap establishes the cryptographic foundations for secure attestation and
|
||||
verification.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- StellaOps CLI installed (`stella` command available)
|
||||
- Network access to TUF repository (or offline trust bundle)
|
||||
- Sufficient permissions to create keys in `/etc/stellaops/keys/`
|
||||
- For keyless mode: OIDC identity provider configured
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Online Bootstrap
|
||||
|
||||
```bash
|
||||
# Initialize trust from organization's TUF repository
|
||||
./devops/scripts/bootstrap-trust.sh \
|
||||
--tuf-url https://trust.example.com/tuf/ \
|
||||
--pin rekor-key-v1
|
||||
```
|
||||
|
||||
### Offline Bootstrap (Air-Gapped)
|
||||
|
||||
```bash
|
||||
# Import pre-packaged trust bundle
|
||||
./devops/scripts/bootstrap-trust-offline.sh \
|
||||
/media/usb/trust-bundle-2026-01-25.tar.zst
|
||||
```
|
||||
|
||||
## Detailed Steps
|
||||
|
||||
### Step 1: Generate Signing Keys (Optional)
|
||||
|
||||
If using local signing keys (not keyless/OIDC):
|
||||
|
||||
```bash
|
||||
# Create key directory
|
||||
mkdir -p /etc/stellaops/keys
|
||||
chmod 700 /etc/stellaops/keys
|
||||
|
||||
# Generate ECDSA P-256 signing key
|
||||
stella keys generate \
|
||||
--type ecdsa-p256 \
|
||||
--out /etc/stellaops/keys/signing-key.pem
|
||||
|
||||
# Or use OpenSSL
|
||||
openssl ecparam -name prime256v1 -genkey -noout \
|
||||
-out /etc/stellaops/keys/signing-key.pem
|
||||
chmod 600 /etc/stellaops/keys/signing-key.pem
|
||||
```
|
||||
|
||||
### Step 2: Initialize TUF Client
|
||||
|
||||
```bash
|
||||
# Initialize with your organization's TUF repository
|
||||
stella trust init \
|
||||
--tuf-url https://trust.example.com/tuf/ \
|
||||
--service-map sigstore-services-v1 \
|
||||
--pin rekor-key-v1 rekor-key-v2
|
||||
|
||||
# Verify initialization
|
||||
stella trust status
|
||||
```
|
||||
|
||||
The `--pin` option specifies which Rekor keys to trust. Pin multiple keys during
|
||||
rotation periods.
|
||||
|
||||
### Step 3: Verify TUF Metadata
|
||||
|
||||
```bash
|
||||
# Check trust status
|
||||
stella trust status --show-keys --show-endpoints
|
||||
|
||||
# Expected output:
|
||||
# TUF Repository: https://trust.example.com/tuf/
|
||||
# Service Map: sigstore-services-v1
|
||||
# Trusted Keys:
|
||||
# - rekor-key-v1 (expires: 2027-01-01)
|
||||
# - rekor-key-v2 (expires: 2028-01-01)
|
||||
# Endpoints:
|
||||
# - Rekor: https://rekor.sigstore.dev
|
||||
# - Fulcio: https://fulcio.sigstore.dev
|
||||
```
|
||||
|
||||
### Step 4: Test Sign/Verify Cycle
|
||||
|
||||
```bash
|
||||
# Create a test payload
|
||||
echo "StellaOps bootstrap test" > /tmp/test-payload.txt
|
||||
|
||||
# Sign with your key
|
||||
stella sign /tmp/test-payload.txt \
|
||||
--key /etc/stellaops/keys/signing-key.pem \
|
||||
--out /tmp/test.sig
|
||||
|
||||
# Verify signature
|
||||
stella verify /tmp/test-payload.txt \
|
||||
--sig /tmp/test.sig
|
||||
|
||||
# Clean up
|
||||
rm /tmp/test-payload.txt /tmp/test.sig
|
||||
```
|
||||
|
||||
### Step 5: Test Rekor Submission (Online Only)
|
||||
|
||||
```bash
|
||||
# Create and submit an attestation
|
||||
stella attest create /tmp/test-payload.txt \
|
||||
--type stellaops.io/predicates/test@v1 \
|
||||
--rekor-submit
|
||||
|
||||
# Verify inclusion in transparency log
|
||||
stella attest verify /tmp/test-payload.txt \
|
||||
--check-inclusion
|
||||
```
|
||||
|
||||
## Offline Bootstrap
|
||||
|
||||
For air-gapped deployments without network access:
|
||||
|
||||
### Create Trust Bundle (Connected System)
|
||||
|
||||
On a system with network access, create a trust bundle:
|
||||
|
||||
```bash
|
||||
stella trust snapshot export \
|
||||
--include-tiles \
|
||||
--out trust-bundle-$(date +%Y-%m-%d).tar.zst
|
||||
```
|
||||
|
||||
### Transfer and Import (Air-Gapped System)
|
||||
|
||||
```bash
|
||||
# Transfer bundle via USB, DVD, or approved data diode
|
||||
# Then import:
|
||||
./devops/scripts/bootstrap-trust-offline.sh \
|
||||
/media/usb/trust-bundle-2026-01-25.tar.zst
|
||||
|
||||
# Optional: Reject stale bundles
|
||||
./devops/scripts/bootstrap-trust-offline.sh \
|
||||
/media/usb/trust-bundle-2026-01-25.tar.zst \
|
||||
--reject-if-stale 7d
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### TUF Client Configuration
|
||||
|
||||
After bootstrap, TUF client configuration is stored in:
|
||||
`~/.local/share/StellaOps/TufCache/`
|
||||
|
||||
Key files:
|
||||
- `root.json` - Root of trust (only updated via ceremony)
|
||||
- `targets.json` - List of trusted targets
|
||||
- `snapshot.json` - Point-in-time snapshot of targets
|
||||
- `timestamp.json` - Freshness guarantee (regularly updated)
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```bash
|
||||
# Override cache directory
|
||||
export STELLAOPS_TUF_CACHE=/custom/path
|
||||
|
||||
# Enable debug logging
|
||||
export STELLAOPS_LOG_LEVEL=debug
|
||||
|
||||
# Offline mode (no network calls)
|
||||
export STELLAOPS_OFFLINE=true
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Error: "TUF metadata verification failed"
|
||||
|
||||
The TUF root key may have been rotated. Obtain the new root.json from your
|
||||
security team and re-bootstrap:
|
||||
|
||||
```bash
|
||||
stella trust init \
|
||||
--tuf-url https://trust.example.com/tuf/ \
|
||||
--root-json /path/to/new/root.json \
|
||||
--force
|
||||
```
|
||||
|
||||
### Error: "Rekor connectivity check failed"
|
||||
|
||||
1. Verify network access to Rekor endpoint
|
||||
2. Check firewall rules for HTTPS (port 443)
|
||||
3. Verify the Rekor URL in service map is correct
|
||||
4. Try forcing a sync: `stella trust sync --force`
|
||||
|
||||
### Error: "Key not found in trust store"
|
||||
|
||||
The pinned key may not exist in the TUF repository. Check available keys:
|
||||
|
||||
```bash
|
||||
stella trust status --show-keys
|
||||
```
|
||||
|
||||
### Offline: "Bundle is stale"
|
||||
|
||||
The trust bundle exceeds the staleness threshold. Obtain a fresh bundle from a
|
||||
connected system:
|
||||
|
||||
```bash
|
||||
# On connected system
|
||||
stella trust snapshot export --out fresh-bundle.tar.zst
|
||||
|
||||
# Transfer and import
|
||||
./devops/scripts/bootstrap-trust-offline.sh fresh-bundle.tar.zst
|
||||
```
|
||||
|
||||
## Maintenance
|
||||
|
||||
### Periodic Sync
|
||||
|
||||
Set up a cron job to keep TUF metadata fresh:
|
||||
|
||||
```bash
|
||||
# Every 6 hours
|
||||
0 */6 * * * /usr/local/bin/stella trust sync --quiet
|
||||
```
|
||||
|
||||
### Updating Air-Gap Bundles
|
||||
|
||||
For air-gapped systems, schedule regular bundle updates based on your
|
||||
organization's freshness requirements (typically 7-30 days).
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Configure CI/CD to use the signing key
|
||||
- Set up key rotation procedures (see `key-rotation-runbook.md`)
|
||||
- Configure monitoring for trust state freshness
|
||||
- For air-gap: Establish bundle transfer schedule
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [TUF Integration Guide](../modules/attestor/tuf-integration.md)
|
||||
- [Key Rotation Runbook](key-rotation-runbook.md)
|
||||
- [Disaster Recovery](disaster-recovery.md)
|
||||
328
docs/operations/disaster-recovery.md
Normal file
328
docs/operations/disaster-recovery.md
Normal file
@@ -0,0 +1,328 @@
|
||||
# StellaOps Disaster Recovery Guide
|
||||
|
||||
> Sprint: SPRINT_20260125_003 - WORKFLOW-003
|
||||
> Last updated: 2026-01-25
|
||||
|
||||
## Overview
|
||||
|
||||
This guide covers disaster recovery procedures for StellaOps trust
|
||||
infrastructure, including Rekor outages, key compromise, and TUF repository
|
||||
failures.
|
||||
|
||||
## Scenario 1: Rekor Service Outage
|
||||
|
||||
### Symptoms
|
||||
- Attestation submissions failing
|
||||
- Verification requests timing out
|
||||
- Circuit breaker reporting OPEN state
|
||||
|
||||
### Immediate Actions
|
||||
|
||||
1. **Verify the outage**
|
||||
```bash
|
||||
# Check Rekor health
|
||||
curl -sf https://rekor.sigstore.dev/api/v1/log | jq .
|
||||
|
||||
# Check circuit breaker state
|
||||
stella trust status --show-circuit-breaker
|
||||
```
|
||||
|
||||
2. **Check if mirror is active**
|
||||
```bash
|
||||
# If mirror failover is enabled, verify it's working
|
||||
stella trust status --show-backends
|
||||
```
|
||||
|
||||
3. **If mirror is not available, swap endpoints via TUF**
|
||||
```bash
|
||||
# On TUF repository admin system
|
||||
./devops/scripts/disaster-swap-endpoint.sh \
|
||||
--repo /path/to/tuf \
|
||||
--new-rekor-url https://rekor-mirror.internal:8080 \
|
||||
--note "Emergency: Production Rekor outage $(date -u)"
|
||||
```
|
||||
|
||||
4. **Publish the update**
|
||||
```bash
|
||||
cd /path/to/tuf
|
||||
./scripts/sign-metadata.sh # Sign updated metadata
|
||||
./scripts/publish.sh # Deploy to TUF server
|
||||
```
|
||||
|
||||
5. **Force client sync (optional, for immediate effect)**
|
||||
```bash
|
||||
stella trust sync --force
|
||||
```
|
||||
|
||||
### Key Principle
|
||||
|
||||
**No client reconfiguration required.** Endpoint changes flow through TUF.
|
||||
Clients discover new endpoints within their configured refresh interval.
|
||||
|
||||
### Recovery
|
||||
|
||||
Once the primary Rekor is restored:
|
||||
|
||||
1. **Swap back to primary**
|
||||
```bash
|
||||
./devops/scripts/disaster-swap-endpoint.sh \
|
||||
--repo /path/to/tuf \
|
||||
--new-rekor-url https://rekor.sigstore.dev \
|
||||
--note "Recovery: Primary Rekor restored"
|
||||
```
|
||||
|
||||
2. **Verify service map published**
|
||||
```bash
|
||||
stella trust sync --force
|
||||
stella trust status --show-endpoints
|
||||
```
|
||||
|
||||
3. **Reset circuit breakers**
|
||||
```bash
|
||||
stella trust reset-circuits
|
||||
```
|
||||
|
||||
## Scenario 2: Rekor Key Compromise
|
||||
|
||||
### Symptoms
|
||||
- Security team reports potential key exposure
|
||||
- Unusual entries in transparency log
|
||||
- Third-party security advisory
|
||||
|
||||
### Immediate Actions
|
||||
|
||||
1. **Assess the compromise scope**
|
||||
- When was the key potentially exposed?
|
||||
- What entries may be affected?
|
||||
- Are there signed entries from the compromised period?
|
||||
|
||||
2. **Emergency key rotation**
|
||||
```bash
|
||||
# Phase 1: Add new key immediately (no grace period)
|
||||
./devops/scripts/rotate-rekor-key.sh add-key \
|
||||
--repo /path/to/tuf \
|
||||
--new-key /secure/new-rekor-key-v2.pub
|
||||
|
||||
# Sign and publish immediately
|
||||
cd /path/to/tuf
|
||||
./scripts/sign-metadata.sh
|
||||
./scripts/publish.sh
|
||||
```
|
||||
|
||||
3. **Force all clients to sync**
|
||||
- Announce emergency update to all teams
|
||||
- Clients should run: `stella trust sync --force`
|
||||
|
||||
4. **Revoke compromised key immediately**
|
||||
```bash
|
||||
# Phase 2: Remove old key (skip grace period due to compromise)
|
||||
./devops/scripts/rotate-rekor-key.sh remove-old \
|
||||
--repo /path/to/tuf \
|
||||
--old-key-name rekor-key-v1
|
||||
|
||||
# Sign and publish
|
||||
cd /path/to/tuf
|
||||
./scripts/sign-metadata.sh
|
||||
./scripts/publish.sh
|
||||
```
|
||||
|
||||
5. **Document the incident**
|
||||
- Log rotation time
|
||||
- Affected key ID and fingerprint
|
||||
- List of potentially affected entries
|
||||
- Remediation steps taken
|
||||
|
||||
### Forensics
|
||||
|
||||
Identify entries signed during the compromise window:
|
||||
|
||||
```bash
|
||||
# Query entries by time range
|
||||
stella rekor query \
|
||||
--after "2026-01-20T00:00:00Z" \
|
||||
--before "2026-01-25T00:00:00Z" \
|
||||
--key-id compromised-key-id
|
||||
```
|
||||
|
||||
## Scenario 3: TUF Repository Unavailable
|
||||
|
||||
### Symptoms
|
||||
- Clients cannot sync trust metadata
|
||||
- `stella trust sync` failing with network errors
|
||||
- TUF timestamp verification failing
|
||||
|
||||
### Immediate Actions
|
||||
|
||||
1. **Diagnose the issue**
|
||||
```bash
|
||||
# Check TUF repository health
|
||||
curl -sf https://trust.example.com/tuf/timestamp.json | jq .
|
||||
|
||||
# Check DNS resolution
|
||||
nslookup trust.example.com
|
||||
|
||||
# Check TLS certificate
|
||||
openssl s_client -connect trust.example.com:443 -servername trust.example.com
|
||||
```
|
||||
|
||||
2. **For clients - extend offline tolerance**
|
||||
```bash
|
||||
# Temporarily allow stale metadata (use with caution)
|
||||
stella trust sync --allow-stale --max-age 7d
|
||||
```
|
||||
|
||||
3. **Restore TUF server**
|
||||
- Check hosting infrastructure
|
||||
- Restore from backup if needed
|
||||
- Verify metadata integrity
|
||||
|
||||
4. **Deploy mirror (if available)**
|
||||
```bash
|
||||
# Update DNS or load balancer to point to mirror
|
||||
# Or update clients directly (less preferred)
|
||||
stella trust init \
|
||||
--tuf-url https://trust-mirror.example.com/tuf/ \
|
||||
--force
|
||||
```
|
||||
|
||||
## Scenario 4: Signing Key Compromise
|
||||
|
||||
### Symptoms
|
||||
- Security team reports key exposure
|
||||
- Unauthorized attestations appearing
|
||||
|
||||
### Immediate Actions
|
||||
|
||||
1. **Revoke the compromised key**
|
||||
```bash
|
||||
./devops/scripts/rotate-signing-key.sh retire \
|
||||
--old-key compromised-key-name
|
||||
```
|
||||
|
||||
2. **Generate new signing key**
|
||||
```bash
|
||||
./devops/scripts/rotate-signing-key.sh generate \
|
||||
--key-type ecdsa-p256
|
||||
```
|
||||
|
||||
3. **Update CI/CD immediately**
|
||||
- Remove compromised key from all pipelines
|
||||
- Add new key
|
||||
- Trigger rebuild of recent releases
|
||||
|
||||
4. **Notify downstream consumers**
|
||||
- Announce key rotation
|
||||
- Provide new public key
|
||||
- Advise re-verification of recent attestations
|
||||
|
||||
## Scenario 5: Root Key Ceremony Required
|
||||
|
||||
### When Required
|
||||
- Scheduled root key rotation (typically annual)
|
||||
- Root key compromise (emergency)
|
||||
- Threshold change for root signatures
|
||||
|
||||
### Procedure
|
||||
|
||||
1. **Schedule ceremony**
|
||||
- Require M-of-N key holders present
|
||||
- Air-gapped ceremony machine
|
||||
- Hardware security modules
|
||||
|
||||
2. **Generate new root**
|
||||
```bash
|
||||
# On air-gapped ceremony machine
|
||||
tuf-ceremony init \
|
||||
--threshold 3 \
|
||||
--keys 5 \
|
||||
--algorithm ed25519
|
||||
```
|
||||
|
||||
3. **Sign new root with old keys**
|
||||
- Requires old threshold of signatures
|
||||
- Ensures continuous trust chain
|
||||
|
||||
4. **Distribute new root**
|
||||
- Publish to TUF repository
|
||||
- Update bootstrap documentation
|
||||
- Notify all operators
|
||||
|
||||
### Air-Gap Considerations
|
||||
|
||||
For air-gapped deployments after root rotation:
|
||||
|
||||
```bash
|
||||
# Export new trust bundle with updated root
|
||||
stella trust snapshot export \
|
||||
--include-root \
|
||||
--out post-rotation-bundle.tar.zst
|
||||
|
||||
# Transfer and import on air-gapped systems
|
||||
./devops/scripts/bootstrap-trust-offline.sh \
|
||||
post-rotation-bundle.tar.zst \
|
||||
--force # Required due to root change
|
||||
```
|
||||
|
||||
## Communication Templates
|
||||
|
||||
### Outage Notification
|
||||
|
||||
```
|
||||
Subject: [StellaOps] Rekor Service Disruption - Failover Active
|
||||
|
||||
Status: Service Degradation
|
||||
Impact: Attestation submissions may be delayed
|
||||
Mitigation: Automatic failover to mirror active
|
||||
|
||||
Action Required: None - clients will auto-discover new endpoint
|
||||
|
||||
Updates: Monitor status at https://status.example.com
|
||||
```
|
||||
|
||||
### Key Rotation Notice
|
||||
|
||||
```
|
||||
Subject: [StellaOps] Emergency Key Rotation - Action Required
|
||||
|
||||
Reason: Security precaution / Scheduled rotation
|
||||
Affected Key: rekor-key-v1 (fingerprint: abc123...)
|
||||
New Key: rekor-key-v2 (fingerprint: def456...)
|
||||
|
||||
Action Required:
|
||||
1. Run: stella trust sync --force
|
||||
2. Verify: stella trust status --show-keys
|
||||
|
||||
Timeline: Old key will be revoked at [DATE/TIME UTC]
|
||||
```
|
||||
|
||||
## Monitoring and Alerting
|
||||
|
||||
### Key Metrics
|
||||
|
||||
- Circuit breaker state changes
|
||||
- TUF metadata freshness
|
||||
- Rekor submission latency
|
||||
- Verification success rate
|
||||
|
||||
### Alert Thresholds
|
||||
|
||||
| Metric | Warning | Critical |
|
||||
|--------|---------|----------|
|
||||
| TUF metadata age | > 12h | > 24h |
|
||||
| Circuit breaker opens | > 2/hour | > 5/hour |
|
||||
| Submission failures | > 5% | > 20% |
|
||||
| Verification failures | > 1% | > 5% |
|
||||
|
||||
## Contacts
|
||||
|
||||
| Role | Contact | Escalation |
|
||||
|------|---------|------------|
|
||||
| TUF Admin | tuf-admin@example.com | On-call |
|
||||
| Security Team | security@example.com | Immediate |
|
||||
| Platform Team | platform@example.com | Business hours |
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Bootstrap Guide](bootstrap-guide.md)
|
||||
- [Key Rotation Runbook](key-rotation-runbook.md)
|
||||
- [TUF Integration Guide](../modules/attestor/tuf-integration.md)
|
||||
@@ -421,9 +421,111 @@ groups:
|
||||
|
||||
---
|
||||
|
||||
## TUF-Based Key Rotation
|
||||
|
||||
> Sprint: SPRINT_20260125_003 - WORKFLOW-007
|
||||
|
||||
For organizations using TUF-based trust distribution, additional key rotation
|
||||
procedures apply to Rekor public keys and TUF metadata signing keys.
|
||||
|
||||
### Rekor Public Key Rotation
|
||||
|
||||
Rekor public keys verify transparency log signatures. Rotation uses a dual-key
|
||||
grace period to ensure all clients sync the new key before removing the old one.
|
||||
|
||||
**Recommended rotation interval:** Annually
|
||||
**Grace period:** 7-14 days
|
||||
|
||||
#### Phase 1: Add New Key
|
||||
|
||||
```bash
|
||||
# Add new Rekor key to TUF repository
|
||||
./devops/scripts/rotate-rekor-key.sh add-key \
|
||||
--repo /path/to/tuf \
|
||||
--new-key rekor-key-v2.pub
|
||||
|
||||
# Sign and publish TUF metadata
|
||||
cd /path/to/tuf
|
||||
./scripts/sign-metadata.sh
|
||||
./scripts/publish.sh
|
||||
```
|
||||
|
||||
#### Phase 2: Grace Period
|
||||
|
||||
During the grace period (7-14 days):
|
||||
- Monitor client sync logs
|
||||
- Verify both keys work for verification
|
||||
- Confirm all clients have updated
|
||||
|
||||
```bash
|
||||
# Check client trust status
|
||||
stella trust status --show-keys
|
||||
# Should show both rekor-key-v1 and rekor-key-v2
|
||||
```
|
||||
|
||||
#### Phase 3: Remove Old Key
|
||||
|
||||
```bash
|
||||
# Remove old key after grace period
|
||||
./devops/scripts/rotate-rekor-key.sh remove-old \
|
||||
--repo /path/to/tuf \
|
||||
--old-key-name rekor-key-v1
|
||||
|
||||
# Sign and publish
|
||||
cd /path/to/tuf
|
||||
./scripts/sign-metadata.sh
|
||||
./scripts/publish.sh
|
||||
```
|
||||
|
||||
### TUF Root Key Rotation
|
||||
|
||||
TUF root keys are the ultimate trust anchor. Rotation is a high-ceremony
|
||||
operation requiring M-of-N key holders.
|
||||
|
||||
**Recommended rotation interval:** 2-3 years
|
||||
**Requires:** Key ceremony with multiple signers
|
||||
|
||||
See [Disaster Recovery](disaster-recovery.md#scenario-5-root-key-ceremony-required)
|
||||
for full root key ceremony procedures.
|
||||
|
||||
### TUF Metadata Signing Key Rotation
|
||||
|
||||
For targets, snapshot, and timestamp keys:
|
||||
|
||||
```bash
|
||||
# Generate new metadata signing key
|
||||
openssl ecparam -name prime256v1 -genkey -noout \
|
||||
-out /secure/targets-key-v2.pem
|
||||
|
||||
# Update root.json to include new key
|
||||
tuf update-root --add-targets-key /secure/targets-key-v2.pem
|
||||
|
||||
# Sign with both old and new keys during transition
|
||||
tuf sign targets --key /secure/targets-key-v1.pem
|
||||
tuf sign targets --key /secure/targets-key-v2.pem
|
||||
|
||||
# After grace period, remove old key from root.json
|
||||
tuf update-root --remove-targets-key /secure/targets-key-v1.pem
|
||||
```
|
||||
|
||||
### Automated Scripts
|
||||
|
||||
Use the provided automation scripts:
|
||||
|
||||
| Script | Purpose |
|
||||
|--------|---------|
|
||||
| `devops/scripts/rotate-rekor-key.sh` | Rekor public key rotation |
|
||||
| `devops/scripts/rotate-signing-key.sh` | Organization signing key rotation |
|
||||
| `devops/trust-repo-template/scripts/revoke-target.sh` | Remove target from TUF |
|
||||
|
||||
---
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Proof Chain API](../api/proofs.md)
|
||||
- [Attestor Architecture](../modules/attestor/architecture.md)
|
||||
- [Signer Architecture](../modules/signer/architecture.md)
|
||||
- [TUF Integration Guide](../modules/attestor/tuf-integration.md)
|
||||
- [Bootstrap Guide](bootstrap-guide.md)
|
||||
- [Disaster Recovery](disaster-recovery.md)
|
||||
- [NIST SP 800-57](https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final) - Key Management Guidelines
|
||||
|
||||
@@ -12,8 +12,11 @@ Guidance on DSSE/TUF roots, rotation, and signed time tokens.
|
||||
- Verification in sealed mode uses bundled roots; no online Rekor needed.
|
||||
- Rotate signing keys with overlapping validity; publish new root in next bundle.
|
||||
|
||||
## TUF (optional)
|
||||
- If using TUF metadata, ship `root.json`, `snapshot.json`, `timestamp.json` with bundles.
|
||||
## TUF (planned enhancement)
|
||||
- **Current**: TUF metadata can be shipped with bundles (`root.json`, `snapshot.json`, `timestamp.json`).
|
||||
- **Planned**: Full TUF client integration for dynamic trust metadata distribution.
|
||||
- See: `SPRINT_20260125_001_Attestor_tuf_trust_foundation.md`
|
||||
- See: `SPRINT_20260125_002_Attestor_trust_automation.md`
|
||||
- In sealed mode, trust only bundled metadata; no remote refresh.
|
||||
|
||||
## Signed time tokens
|
||||
|
||||
Reference in New Issue
Block a user