test
This commit is contained in:
336
docs/modules/policy/evidence-hooks.md
Normal file
336
docs/modules/policy/evidence-hooks.md
Normal file
@@ -0,0 +1,336 @@
|
||||
# Evidence Hooks Reference
|
||||
|
||||
## Overview
|
||||
|
||||
**Evidence Hooks** require specific attestations before an exception can be approved. This ensures exceptions are backed by verifiable proof, not just assertions.
|
||||
|
||||
## Hook Model
|
||||
|
||||
```yaml
|
||||
evidenceHooks:
|
||||
- hookId: "feature-flag-off"
|
||||
type: FeatureFlagDisabled
|
||||
description: "Feature flag must be disabled in production"
|
||||
isMandatory: true
|
||||
maxAge: PT24H # ISO 8601 duration
|
||||
minTrustScore: 0.8
|
||||
```
|
||||
|
||||
## Hook Types
|
||||
|
||||
### FeatureFlagDisabled
|
||||
|
||||
Requires attestation that a feature flag is disabled.
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| flagName | string | Name of the feature flag |
|
||||
| environment | string | Target environment |
|
||||
| attestedAt | timestamp | When flag state was verified |
|
||||
|
||||
**Evidence Example:**
|
||||
```json
|
||||
{
|
||||
"type": "FeatureFlagDisabled",
|
||||
"flagName": "EXPERIMENTAL_TEMPLATE_ENGINE",
|
||||
"environment": "production",
|
||||
"attestedAt": "2024-12-22T10:00:00Z",
|
||||
"source": "launchdarkly"
|
||||
}
|
||||
```
|
||||
|
||||
### BackportMerged
|
||||
|
||||
Requires attestation that a security backport was merged.
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| prUrl | string | Pull request URL |
|
||||
| commitHash | string | Merged commit hash |
|
||||
| mergedAt | timestamp | When PR was merged |
|
||||
|
||||
**Evidence Example:**
|
||||
```json
|
||||
{
|
||||
"type": "BackportMerged",
|
||||
"prUrl": "https://github.com/org/repo/pull/123",
|
||||
"commitHash": "abc123...",
|
||||
"mergedAt": "2024-12-22T09:30:00Z",
|
||||
"mergedBy": "security-team"
|
||||
}
|
||||
```
|
||||
|
||||
### CompensatingControl
|
||||
|
||||
Requires attestation of a compensating security control.
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| controlType | string | Type of control (WAF, RASP, etc.) |
|
||||
| controlId | string | Control identifier |
|
||||
| description | string | How control mitigates risk |
|
||||
|
||||
**Evidence Example:**
|
||||
```json
|
||||
{
|
||||
"type": "CompensatingControl",
|
||||
"controlType": "WAF",
|
||||
"controlId": "rule-block-template-injection",
|
||||
"description": "WAF rule blocks template injection patterns",
|
||||
"deployedAt": "2024-12-22T08:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### SecurityReview
|
||||
|
||||
Requires attestation of completed security review.
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| reviewId | string | Review identifier |
|
||||
| reviewer | string | Who performed review |
|
||||
| outcome | string | Review outcome |
|
||||
|
||||
### RuntimeMitigation
|
||||
|
||||
Requires attestation of runtime mitigation in place.
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| mitigationType | string | Type of mitigation |
|
||||
| configuration | object | Mitigation configuration |
|
||||
|
||||
### WAFRuleDeployed
|
||||
|
||||
Requires attestation of WAF rule deployment.
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| ruleId | string | WAF rule identifier |
|
||||
| provider | string | WAF provider |
|
||||
| deployedAt | timestamp | Deployment time |
|
||||
|
||||
### CustomAttestation
|
||||
|
||||
Generic attestation for custom evidence types.
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| predicateType | string | Custom predicate type URI |
|
||||
| payload | object | Custom payload |
|
||||
|
||||
## Validation Rules
|
||||
|
||||
### Freshness (maxAge)
|
||||
|
||||
Evidence must be recent enough:
|
||||
|
||||
```yaml
|
||||
maxAge: PT24H # 24 hours
|
||||
maxAge: P7D # 7 days
|
||||
maxAge: PT1H # 1 hour
|
||||
```
|
||||
|
||||
If evidence is older than maxAge, it's marked as **Expired**.
|
||||
|
||||
### Trust Score (minTrustScore)
|
||||
|
||||
Evidence source must meet minimum trust:
|
||||
|
||||
```yaml
|
||||
minTrustScore: 0.8 # 80% trust required
|
||||
```
|
||||
|
||||
Trust scores come from the source registry.
|
||||
|
||||
### Signature Verification
|
||||
|
||||
If evidence includes a DSSE envelope, signature is verified:
|
||||
|
||||
```json
|
||||
{
|
||||
"content": { ... },
|
||||
"dsseEnvelope": "eyJwYXlsb2FkIjoi...",
|
||||
"signatureVerified": true
|
||||
}
|
||||
```
|
||||
|
||||
### Schema Validation
|
||||
|
||||
Custom attestations can require schema validation:
|
||||
|
||||
```yaml
|
||||
validationSchema: "https://stellaops.io/schemas/evidence/feature-flag/v1"
|
||||
```
|
||||
|
||||
## Validation States
|
||||
|
||||
| State | Description |
|
||||
|-------|-------------|
|
||||
| `Pending` | Evidence submitted, not yet validated |
|
||||
| `Valid` | Evidence passes all validation |
|
||||
| `Invalid` | Evidence fails validation |
|
||||
| `Expired` | Evidence older than maxAge |
|
||||
| `InsufficientTrust` | Source trust score too low |
|
||||
|
||||
## Submission Flow
|
||||
|
||||
```
|
||||
1. User selects exception to approve
|
||||
2. System shows required evidence hooks
|
||||
3. User submits evidence for each hook:
|
||||
a. Upload attestation file
|
||||
b. Link to external system
|
||||
c. Generate attestation in-place
|
||||
4. System validates each submission
|
||||
5. If all mandatory hooks satisfied:
|
||||
a. Exception can be approved
|
||||
6. If any mandatory hooks unsatisfied:
|
||||
a. Approval blocked
|
||||
b. Missing evidence highlighted
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### POST /exceptions/{id}/evidence
|
||||
|
||||
Submit evidence for a hook.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"hookId": "feature-flag-off",
|
||||
"type": "FeatureFlagDisabled",
|
||||
"reference": "launchdarkly://flags/EXPERIMENTAL_TEMPLATE_ENGINE",
|
||||
"content": {
|
||||
"flagName": "EXPERIMENTAL_TEMPLATE_ENGINE",
|
||||
"environment": "production",
|
||||
"state": "off"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET /exceptions/{id}/evidence
|
||||
|
||||
Get all submitted evidence for an exception.
|
||||
|
||||
### GET /exceptions/{id}/evidence/status
|
||||
|
||||
Get evidence satisfaction status.
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"isSatisfied": false,
|
||||
"missingEvidence": [
|
||||
{
|
||||
"hookId": "backport-merged",
|
||||
"type": "BackportMerged",
|
||||
"description": "Security backport must be merged"
|
||||
}
|
||||
],
|
||||
"validEvidence": [
|
||||
{
|
||||
"hookId": "feature-flag-off",
|
||||
"type": "FeatureFlagDisabled",
|
||||
"validatedAt": "2024-12-22T10:00:00Z"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## UI Integration
|
||||
|
||||
### Evidence Requirements Panel
|
||||
|
||||
Shows required evidence with status:
|
||||
|
||||
```
|
||||
Evidence Requirements
|
||||
---------------------
|
||||
[x] Feature flag disabled (Verified 2h ago)
|
||||
[ ] Backport PR merged (Missing)
|
||||
[x] WAF rule deployed (Verified 1d ago)
|
||||
|
||||
[Submit Missing Evidence]
|
||||
```
|
||||
|
||||
### Evidence Upload Modal
|
||||
|
||||
For each hook type:
|
||||
1. File upload for attestations
|
||||
2. URL input for external references
|
||||
3. Form for in-place attestation
|
||||
|
||||
### Blocking Indicator
|
||||
|
||||
When evidence is missing:
|
||||
- Approve button disabled
|
||||
- Clear message: "Cannot approve: missing evidence"
|
||||
- Link to evidence requirements
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Mandatory = Critical**: Only mark truly required evidence as mandatory
|
||||
2. **Reasonable maxAge**: Balance freshness with operational burden
|
||||
3. **Trust Scores**: Configure source trust appropriately
|
||||
4. **Documentation**: Document what each evidence type means
|
||||
5. **Automation**: Integrate with systems to auto-generate attestations
|
||||
|
||||
## DSSE Attestation Format
|
||||
|
||||
Evidence can be wrapped in DSSE for integrity:
|
||||
|
||||
```json
|
||||
{
|
||||
"payloadType": "application/vnd.stellaops.evidence+json",
|
||||
"payload": "<base64-encoded-evidence>",
|
||||
"signatures": [
|
||||
{
|
||||
"keyid": "key-123",
|
||||
"sig": "<base64-signature>"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Example Hook Configurations
|
||||
|
||||
### Critical CVE Policy
|
||||
|
||||
```yaml
|
||||
evidenceHooks:
|
||||
- hookId: "security-review"
|
||||
type: SecurityReview
|
||||
description: "Security team review required"
|
||||
isMandatory: true
|
||||
- hookId: "compensating-control"
|
||||
type: CompensatingControl
|
||||
description: "Compensating control must be in place"
|
||||
isMandatory: true
|
||||
- hookId: "stakeholder-approval"
|
||||
type: CustomAttestation
|
||||
description: "Business stakeholder approval"
|
||||
isMandatory: true
|
||||
validationSchema: "https://stellaops.io/schemas/evidence/stakeholder-approval/v1"
|
||||
```
|
||||
|
||||
### Standard Policy
|
||||
|
||||
```yaml
|
||||
evidenceHooks:
|
||||
- hookId: "justification"
|
||||
type: CustomAttestation
|
||||
description: "Written justification required"
|
||||
isMandatory: true
|
||||
- hookId: "compensating-control"
|
||||
type: CompensatingControl
|
||||
description: "Compensating control recommended"
|
||||
isMandatory: false
|
||||
```
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Recheck Policy](./recheck-policy.md)
|
||||
- [Exception Workflow](../../api/exceptions.md)
|
||||
- [DSSE Attestations](../attestor/dsse.md)
|
||||
251
docs/modules/policy/recheck-policy.md
Normal file
251
docs/modules/policy/recheck-policy.md
Normal file
@@ -0,0 +1,251 @@
|
||||
# Recheck Policy Reference
|
||||
|
||||
## Overview
|
||||
|
||||
A **Recheck Policy** defines conditions that trigger automatic re-evaluation of an exception. When conditions are met, the exception may be flagged for review, require re-approval, or be automatically revoked.
|
||||
|
||||
## Policy Model
|
||||
|
||||
```yaml
|
||||
recheckPolicy:
|
||||
policyId: "policy-critical-cves"
|
||||
name: "Critical CVE Recheck"
|
||||
conditions:
|
||||
- type: EPSSAbove
|
||||
threshold: 0.5
|
||||
action: RequireReapproval
|
||||
- type: ReachGraphChange
|
||||
action: Block
|
||||
- type: KEVFlagged
|
||||
action: Block
|
||||
- type: ExpiryWithin
|
||||
threshold: 7 # days
|
||||
action: Warn
|
||||
defaultAction: Warn
|
||||
isActive: true
|
||||
```
|
||||
|
||||
## Condition Types
|
||||
|
||||
### EPSSAbove
|
||||
|
||||
Triggers when EPSS score exceeds threshold.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| threshold | decimal | EPSS score threshold (0.0-1.0) |
|
||||
| action | RecheckAction | Action when triggered |
|
||||
|
||||
**Example:**
|
||||
```yaml
|
||||
- type: EPSSAbove
|
||||
threshold: 0.5
|
||||
action: RequireReapproval
|
||||
```
|
||||
|
||||
### CVSSAbove
|
||||
|
||||
Triggers when CVSS score exceeds threshold.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| threshold | decimal | CVSS score threshold (0.0-10.0) |
|
||||
| action | RecheckAction | Action when triggered |
|
||||
|
||||
### ReachGraphChange
|
||||
|
||||
Triggers when reachability graph changes (new paths discovered).
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| action | RecheckAction | Action when triggered |
|
||||
|
||||
**Use case:** Exception was based on "unreachable" status; new analysis shows reachability.
|
||||
|
||||
### UnknownsAbove
|
||||
|
||||
Triggers when unknown budget exceeds threshold.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| threshold | integer | Maximum allowed unknowns |
|
||||
| action | RecheckAction | Action when triggered |
|
||||
|
||||
### KEVFlagged
|
||||
|
||||
Triggers when CVE is added to CISA KEV catalog.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| action | RecheckAction | Action when triggered |
|
||||
|
||||
**Best practice:** Always use `Block` action for KEV additions.
|
||||
|
||||
### VEXStatusChange
|
||||
|
||||
Triggers when VEX status changes (e.g., NotAffected → Affected).
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| action | RecheckAction | Action when triggered |
|
||||
|
||||
### NewCVEInPackage
|
||||
|
||||
Triggers when new CVE is discovered in the same package.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| action | RecheckAction | Action when triggered |
|
||||
|
||||
### ExpiryWithin
|
||||
|
||||
Triggers when exception nears expiry.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| threshold | integer | Days before expiry |
|
||||
| action | RecheckAction | Action when triggered |
|
||||
|
||||
### PackageVersionChange
|
||||
|
||||
Triggers when package version changes in artifact.
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------|-------------|
|
||||
| action | RecheckAction | Action when triggered |
|
||||
|
||||
## Actions
|
||||
|
||||
### Warn
|
||||
|
||||
Log warning but allow exception to remain active.
|
||||
|
||||
- Appears in audit log
|
||||
- Visible in exception details
|
||||
- Does not block deployment
|
||||
|
||||
### RequireReapproval
|
||||
|
||||
Move exception back to "pending" status requiring re-approval.
|
||||
|
||||
- Notifies original approvers
|
||||
- Exception inactive until re-approved
|
||||
- Evidence may need updating
|
||||
|
||||
### Revoke
|
||||
|
||||
Automatically revoke the exception.
|
||||
|
||||
- Exception becomes inactive immediately
|
||||
- Audit log entry created
|
||||
- Notification sent
|
||||
|
||||
### Block
|
||||
|
||||
Fail build/deployment pipeline.
|
||||
|
||||
- CI/CD gate returns failure
|
||||
- Requires manual intervention
|
||||
- Most severe action
|
||||
|
||||
## Environment Scoping
|
||||
|
||||
Conditions can be scoped to specific environments:
|
||||
|
||||
```yaml
|
||||
- type: EPSSAbove
|
||||
threshold: 0.3
|
||||
environmentScope:
|
||||
- prod
|
||||
- staging
|
||||
action: Block
|
||||
- type: EPSSAbove
|
||||
threshold: 0.7
|
||||
environmentScope:
|
||||
- dev
|
||||
action: Warn
|
||||
```
|
||||
|
||||
## Evaluation Flow
|
||||
|
||||
```
|
||||
1. Scan triggered
|
||||
2. Get active exceptions for artifact
|
||||
3. For each exception with recheck policy:
|
||||
a. Evaluate each condition
|
||||
b. Check environment scope
|
||||
c. Record triggered conditions
|
||||
4. Determine highest-priority action
|
||||
5. Apply action (warn/reapproval/revoke/block)
|
||||
6. Update exception with recheck result
|
||||
```
|
||||
|
||||
## Build Gate Integration
|
||||
|
||||
Recheck policies integrate with build gates:
|
||||
|
||||
```yaml
|
||||
# In CI/CD pipeline
|
||||
- name: check-exceptions
|
||||
uses: stellaops/exception-gate@v1
|
||||
with:
|
||||
artifact: ${{ env.IMAGE_DIGEST }}
|
||||
environment: production
|
||||
fail-on: block
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Start with Warn**: Begin with warning actions, escalate based on data
|
||||
2. **KEV = Block**: Always block on KEV additions
|
||||
3. **Environment Tiers**: Stricter policies for production
|
||||
4. **Regular Review**: Review triggered conditions monthly
|
||||
5. **Document Rationale**: Explain threshold choices
|
||||
|
||||
## Example Policies
|
||||
|
||||
### High-Security Policy
|
||||
|
||||
```yaml
|
||||
recheckPolicy:
|
||||
policyId: "high-security"
|
||||
name: "High Security Recheck"
|
||||
conditions:
|
||||
- type: EPSSAbove
|
||||
threshold: 0.3
|
||||
action: Block
|
||||
- type: CVSSAbove
|
||||
threshold: 7.0
|
||||
action: RequireReapproval
|
||||
- type: KEVFlagged
|
||||
action: Block
|
||||
- type: ReachGraphChange
|
||||
action: Block
|
||||
- type: VEXStatusChange
|
||||
action: RequireReapproval
|
||||
defaultAction: Warn
|
||||
```
|
||||
|
||||
### Standard Policy
|
||||
|
||||
```yaml
|
||||
recheckPolicy:
|
||||
policyId: "standard"
|
||||
name: "Standard Recheck"
|
||||
conditions:
|
||||
- type: EPSSAbove
|
||||
threshold: 0.7
|
||||
action: RequireReapproval
|
||||
- type: KEVFlagged
|
||||
action: Block
|
||||
- type: ExpiryWithin
|
||||
threshold: 14
|
||||
action: Warn
|
||||
defaultAction: Warn
|
||||
```
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Evidence Hooks](./evidence-hooks.md)
|
||||
- [Exception API](../../api/exceptions.md)
|
||||
- [Build Gates](../ci/recipes.md)
|
||||
Reference in New Issue
Block a user