17 KiB
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:
{
"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:
{
"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:
{
"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:
{
"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:
{
"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:
{
"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:
# 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:
{
"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:
{
"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
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
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 - Exception enforcement
- Notification Flow - Approval notifications
- Multi-Tenant Policy Rollout Flow - Policy context