470 lines
17 KiB
Markdown
470 lines
17 KiB
Markdown
# Exception Approval Workflow
|
|
|
|
## Overview
|
|
|
|
The Exception Approval Workflow describes how StellaOps handles policy exception requests, from initial submission through multi-level approval, time-limited grants, and expiration tracking. This flow ensures exceptions are documented, justified, and automatically expire.
|
|
|
|
**Business Value**: Maintain security governance while allowing controlled exceptions for legitimate business needs, with full audit trail and automatic expiration.
|
|
|
|
## Actors
|
|
|
|
| Actor | Type | Role |
|
|
|-------|------|------|
|
|
| Developer | Human | Requests exception |
|
|
| Team Lead | Human | First-level approval |
|
|
| Security Team | Human | Security review and approval |
|
|
| CISO | Human | Final approval (high severity) |
|
|
| Policy Engine | Service | Enforces exception |
|
|
| Scheduler | Service | Tracks expiration |
|
|
| Notify | Service | Sends alerts |
|
|
|
|
## Prerequisites
|
|
|
|
- Policy violation detected
|
|
- Exception workflow configured
|
|
- Approval chain defined
|
|
- Notification channels configured
|
|
|
|
## Exception Types
|
|
|
|
| Type | Description | Max Duration | Approval Level |
|
|
|------|-------------|--------------|----------------|
|
|
| Temporary | Time-limited deferral | 30 days | Team Lead |
|
|
| Extended | Business justification | 90 days | Security Team |
|
|
| Permanent | Architectural constraint | Indefinite | CISO |
|
|
| Emergency | Incident response | 7 days | Security Team |
|
|
|
|
## Flow Diagram
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────────────────────────┐
|
|
│ Exception Approval Workflow │
|
|
└─────────────────────────────────────────────────────────────────────────────────┘
|
|
|
|
┌───────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ ┌───────────┐
|
|
│ Developer │ │ Team Lead│ │ Security │ │ Policy │ │Scheduler│ │ Notify │
|
|
└─────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ └───┬────┘ └─────┬─────┘
|
|
│ │ │ │ │ │
|
|
│ Request │ │ │ │ │
|
|
│ exception │ │ │ │ │
|
|
│───────────────────────────────────────> │ │
|
|
│ │ │ │ │ │
|
|
│ │ │ │ Validate │ │
|
|
│ │ │ │ request │ │
|
|
│ │ │ │───┐ │ │
|
|
│ │ │ │ │ │ │
|
|
│ │ │ │<──┘ │ │
|
|
│ │ │ │ │ │
|
|
│ │ │ │ Notify │ │
|
|
│ │ │ │ approvers │ │
|
|
│ │ │ │──────────────────────────>
|
|
│ │ │ │ │ │
|
|
│ │ Approval │ │ │ │ Send
|
|
│ │ request │ │ │ │ email
|
|
│ │<──────────────────────────────────────────────────
|
|
│ │ │ │ │ │
|
|
│ │ Review & │ │ │ │
|
|
│ │ approve │ │ │ │
|
|
│ │───────────────────────────> │ │
|
|
│ │ │ │ │ │
|
|
│ │ │ │ [If high │ │
|
|
│ │ │ │ severity] │ │
|
|
│ │ │ │───────────────────────────>
|
|
│ │ │ │ │ │
|
|
│ │ │ Approval │ │ │
|
|
│ │ │ request │ │ │
|
|
│ │ │<──────────────────────────────────────
|
|
│ │ │ │ │ │
|
|
│ │ │ Review & │ │ │
|
|
│ │ │ approve │ │ │
|
|
│ │ │───────────>│ │ │
|
|
│ │ │ │ │ │
|
|
│ │ │ │ Grant │ │
|
|
│ │ │ │ exception │ │
|
|
│ │ │ │───┐ │ │
|
|
│ │ │ │ │ │ │
|
|
│ │ │ │<──┘ │ │
|
|
│ │ │ │ │ │
|
|
│ │ │ │ Schedule │ │
|
|
│ │ │ │ expiration│ │
|
|
│ │ │ │──────────>│ │
|
|
│ │ │ │ │ │
|
|
│ │ │ │ │ Schedule │
|
|
│ │ │ │ │ reminders │
|
|
│ │ │ │ │───┐ │
|
|
│ │ │ │ │ │ │
|
|
│ │ │ │ │<──┘ │
|
|
│ │ │ │ │ │
|
|
│ Exception │ │ │ │ │
|
|
│ granted │ │ │ │ │
|
|
│<───────────────────────────────────────────────────────────────
|
|
│ │ │ │ │ │
|
|
│ │ │ │ │[7d before] │
|
|
│ │ │ │ │ expiration │
|
|
│ │ │ │ │────────────>
|
|
│ │ │ │ │ │
|
|
│ Expiration │ │ │ │ │ Notify
|
|
│ warning │ │ │ │ │ owner
|
|
│<──────────────────────────────────────────────────────────────
|
|
│ │ │ │ │ │
|
|
```
|
|
|
|
## Step-by-Step
|
|
|
|
### 1. Exception Request
|
|
|
|
Developer submits exception request:
|
|
|
|
```json
|
|
{
|
|
"request_id": "exc-req-123",
|
|
"requester": "developer@acme.com",
|
|
"created_at": "2024-12-29T10:00:00Z",
|
|
"finding": {
|
|
"scan_id": "scan-abc123",
|
|
"cve": "CVE-2024-1234",
|
|
"package": "pkg:npm/lodash@4.17.20",
|
|
"severity": "high",
|
|
"policy_violation": "no-high-production"
|
|
},
|
|
"exception_type": "temporary",
|
|
"requested_duration": "30d",
|
|
"justification": {
|
|
"business_reason": "Upgrading lodash breaks critical authentication flow. Need time to refactor.",
|
|
"risk_acceptance": "Vulnerability requires prototype pollution which is not exploitable in our usage pattern.",
|
|
"mitigation_plan": "WAF rule deployed to block exploitation vectors. Ticket JIRA-1234 tracks fix.",
|
|
"remediation_deadline": "2025-01-28"
|
|
},
|
|
"scope": {
|
|
"images": ["docker.io/myorg/auth-service:*"],
|
|
"environments": ["production"]
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. Request Validation
|
|
|
|
Policy Engine validates the request:
|
|
|
|
```json
|
|
{
|
|
"validation": {
|
|
"request_id": "exc-req-123",
|
|
"valid": true,
|
|
"checks": [
|
|
{"check": "cve_exists", "passed": true},
|
|
{"check": "policy_violation_active", "passed": true},
|
|
{"check": "requester_authorized", "passed": true},
|
|
{"check": "scope_valid", "passed": true},
|
|
{"check": "duration_within_limits", "passed": true}
|
|
],
|
|
"required_approvers": [
|
|
{"role": "team_lead", "required": true},
|
|
{"role": "security_team", "required": true, "reason": "high_severity"}
|
|
],
|
|
"approval_deadline": "2024-12-31T10:00:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. Approval Chain Notification
|
|
|
|
Notify sends approval requests:
|
|
|
|
```json
|
|
{
|
|
"notification": {
|
|
"type": "exception_approval_request",
|
|
"recipients": [
|
|
{"email": "team-lead@acme.com", "role": "team_lead"},
|
|
{"channel": "slack", "target": "#security-approvals"}
|
|
],
|
|
"content": {
|
|
"request_id": "exc-req-123",
|
|
"requester": "developer@acme.com",
|
|
"cve": "CVE-2024-1234",
|
|
"severity": "high",
|
|
"justification_summary": "Upgrading breaks auth flow. WAF mitigation in place.",
|
|
"approval_url": "https://console.stellaops.local/exceptions/exc-req-123/approve"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 4. First-Level Approval (Team Lead)
|
|
|
|
Team Lead reviews and approves:
|
|
|
|
```json
|
|
{
|
|
"approval": {
|
|
"request_id": "exc-req-123",
|
|
"approver": "team-lead@acme.com",
|
|
"role": "team_lead",
|
|
"decision": "approved",
|
|
"approved_at": "2024-12-29T11:00:00Z",
|
|
"conditions": [
|
|
"Must have JIRA ticket for remediation",
|
|
"Weekly status update required"
|
|
],
|
|
"notes": "Verified WAF rule is active. Approve with conditions."
|
|
}
|
|
}
|
|
```
|
|
|
|
### 5. Security Review (Second Level)
|
|
|
|
Security team reviews high-severity exceptions:
|
|
|
|
```json
|
|
{
|
|
"security_review": {
|
|
"request_id": "exc-req-123",
|
|
"reviewer": "security-analyst@acme.com",
|
|
"role": "security_team",
|
|
"review_date": "2024-12-29T14:00:00Z",
|
|
"assessment": {
|
|
"risk_rating": "medium",
|
|
"exploitation_likelihood": "low",
|
|
"mitigation_effectiveness": "high",
|
|
"recommendation": "approve_with_monitoring"
|
|
},
|
|
"decision": "approved",
|
|
"conditions": [
|
|
"Enable runtime monitoring for auth-service",
|
|
"Review exception at 15-day mark"
|
|
],
|
|
"approved_duration": "30d" // May reduce requested duration
|
|
}
|
|
}
|
|
```
|
|
|
|
### 6. Exception Grant
|
|
|
|
Policy Engine activates the exception:
|
|
|
|
```json
|
|
{
|
|
"exception": {
|
|
"exception_id": "exc-456",
|
|
"request_id": "exc-req-123",
|
|
"status": "active",
|
|
"granted_at": "2024-12-29T14:30:00Z",
|
|
"granted_by": ["team-lead@acme.com", "security-analyst@acme.com"],
|
|
"finding": {
|
|
"cve": "CVE-2024-1234",
|
|
"package": "pkg:npm/lodash@4.17.20"
|
|
},
|
|
"scope": {
|
|
"images": ["docker.io/myorg/auth-service:*"],
|
|
"policy_rules": ["no-high-production"]
|
|
},
|
|
"validity": {
|
|
"starts_at": "2024-12-29T14:30:00Z",
|
|
"expires_at": "2025-01-28T14:30:00Z",
|
|
"duration": "30d"
|
|
},
|
|
"conditions": {
|
|
"require_jira_ticket": true,
|
|
"weekly_status_update": true,
|
|
"runtime_monitoring": true,
|
|
"mid_point_review": "2025-01-13T14:30:00Z"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 7. Exception Enforcement
|
|
|
|
During policy evaluation, exception is applied:
|
|
|
|
```yaml
|
|
# Policy evaluation with exception
|
|
finding:
|
|
cve: CVE-2024-1234
|
|
package: pkg:npm/lodash@4.17.20
|
|
severity: high
|
|
|
|
exception_check:
|
|
exception_id: exc-456
|
|
scope_match: true
|
|
still_valid: true
|
|
conditions_met: true
|
|
|
|
verdict:
|
|
original: FAIL
|
|
with_exception: PASS
|
|
reason: "Exception exc-456 active until 2025-01-28"
|
|
```
|
|
|
|
### 8. Expiration Tracking
|
|
|
|
Scheduler manages exception lifecycle:
|
|
|
|
```json
|
|
{
|
|
"exception_schedule": {
|
|
"exception_id": "exc-456",
|
|
"events": [
|
|
{
|
|
"type": "mid_point_review",
|
|
"scheduled_at": "2025-01-13T14:30:00Z",
|
|
"notify": ["requester", "approvers"]
|
|
},
|
|
{
|
|
"type": "expiration_warning",
|
|
"scheduled_at": "2025-01-21T14:30:00Z",
|
|
"days_before": 7,
|
|
"notify": ["requester", "team_lead"]
|
|
},
|
|
{
|
|
"type": "expiration_final_warning",
|
|
"scheduled_at": "2025-01-27T14:30:00Z",
|
|
"days_before": 1,
|
|
"notify": ["requester", "team_lead", "security_team"]
|
|
},
|
|
{
|
|
"type": "expiration",
|
|
"scheduled_at": "2025-01-28T14:30:00Z",
|
|
"action": "deactivate_exception"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
### 9. Renewal Request (If Needed)
|
|
|
|
Before expiration, requester can request renewal:
|
|
|
|
```json
|
|
{
|
|
"renewal_request": {
|
|
"exception_id": "exc-456",
|
|
"requested_extension": "30d",
|
|
"reason": "Refactoring taking longer than expected. PR in review.",
|
|
"progress_update": {
|
|
"jira_ticket": "JIRA-1234",
|
|
"status": "In Review",
|
|
"completion_percentage": 75
|
|
},
|
|
"new_deadline": "2025-02-27"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Approval Matrix
|
|
|
|
| Severity | Exception Type | Required Approvers |
|
|
|----------|---------------|-------------------|
|
|
| Low | Temporary | Team Lead |
|
|
| Medium | Temporary | Team Lead |
|
|
| High | Temporary | Team Lead + Security |
|
|
| Critical | Any | Team Lead + Security + CISO |
|
|
| Any | Extended | Team Lead + Security |
|
|
| Any | Permanent | Security + CISO |
|
|
| Any | Emergency | Security (expedited) |
|
|
|
|
## Data Contracts
|
|
|
|
### Exception Request Schema
|
|
|
|
```typescript
|
|
interface ExceptionRequest {
|
|
request_id: string;
|
|
requester: string;
|
|
created_at: string;
|
|
finding: {
|
|
scan_id: string;
|
|
cve: string;
|
|
package: string;
|
|
severity: 'critical' | 'high' | 'medium' | 'low';
|
|
policy_violation: string;
|
|
};
|
|
exception_type: 'temporary' | 'extended' | 'permanent' | 'emergency';
|
|
requested_duration?: string;
|
|
justification: {
|
|
business_reason: string;
|
|
risk_acceptance: string;
|
|
mitigation_plan: string;
|
|
remediation_deadline?: string;
|
|
};
|
|
scope: {
|
|
images?: string[];
|
|
environments?: string[];
|
|
tenants?: string[];
|
|
};
|
|
}
|
|
```
|
|
|
|
### Exception Status Schema
|
|
|
|
```typescript
|
|
interface Exception {
|
|
exception_id: string;
|
|
request_id: string;
|
|
status: 'pending' | 'approved' | 'rejected' | 'active' | 'expired' | 'revoked';
|
|
finding: {
|
|
cve: string;
|
|
package: string;
|
|
};
|
|
scope: {
|
|
images: string[];
|
|
policy_rules: string[];
|
|
};
|
|
validity: {
|
|
starts_at: string;
|
|
expires_at: string;
|
|
duration: string;
|
|
};
|
|
approvals: Array<{
|
|
approver: string;
|
|
role: string;
|
|
decision: 'approved' | 'rejected';
|
|
timestamp: string;
|
|
conditions?: string[];
|
|
notes?: string;
|
|
}>;
|
|
audit_trail: AuditEntry[];
|
|
}
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
| Error | Recovery |
|
|
|-------|----------|
|
|
| Approval timeout | Escalate to next level or reject |
|
|
| Approver unavailable | Route to backup approver |
|
|
| Scope too broad | Request scope refinement |
|
|
| Missing justification | Request additional details |
|
|
| Exception conflict | Flag for manual review |
|
|
|
|
## Observability
|
|
|
|
### Metrics
|
|
|
|
| Metric | Type | Labels |
|
|
|--------|------|--------|
|
|
| `exception_requests_total` | Counter | `type`, `severity` |
|
|
| `exception_approvals_total` | Counter | `decision`, `approver_role` |
|
|
| `exception_active_count` | Gauge | `severity` |
|
|
| `exception_approval_duration_hours` | Histogram | `severity` |
|
|
| `exception_expiring_7d` | Gauge | - |
|
|
|
|
### Key Log Events
|
|
|
|
| Event | Level | Fields |
|
|
|-------|-------|--------|
|
|
| `exception.requested` | INFO | `request_id`, `cve`, `requester` |
|
|
| `exception.approved` | INFO | `exception_id`, `approver`, `duration` |
|
|
| `exception.rejected` | INFO | `request_id`, `approver`, `reason` |
|
|
| `exception.activated` | INFO | `exception_id`, `scope` |
|
|
| `exception.expiring` | WARN | `exception_id`, `days_remaining` |
|
|
| `exception.expired` | INFO | `exception_id` |
|
|
|
|
## Related Flows
|
|
|
|
- [Policy Evaluation Flow](04-policy-evaluation-flow.md) - Exception enforcement
|
|
- [Notification Flow](05-notification-flow.md) - Approval notifications
|
|
- [Multi-Tenant Policy Rollout Flow](14-multi-tenant-policy-rollout-flow.md) - Policy context
|