127 lines
3.5 KiB
Python
127 lines
3.5 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any, Literal
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
from .ai_security import Confidence, Severity
|
|
|
|
|
|
RemediationPlanStatus = Literal['draft', 'reviewed', 'approved_for_manual_execution', 'dismissed']
|
|
RemediationSourceType = Literal['security_finding', 'security_recommendation', 'media_issue', 'inventory', 'connector', 'policy', 'secret', 'unknown']
|
|
RemediationStepType = Literal[
|
|
'open_page',
|
|
'configure_secret',
|
|
'bind_connector',
|
|
'review_policy',
|
|
'request_approval',
|
|
'run_readonly_check',
|
|
'manual_external_change',
|
|
'blocked_action',
|
|
'documentation',
|
|
]
|
|
DryRunStatus = Literal['pass', 'warning', 'blocked']
|
|
|
|
|
|
class RemediationEvidence(BaseModel):
|
|
source: str
|
|
label: str
|
|
value: Any = None
|
|
redacted: bool = False
|
|
|
|
|
|
class RemediationApprovalRequirement(BaseModel):
|
|
actionId: str
|
|
target: str
|
|
reason: str
|
|
risk: str
|
|
policyDecision: str
|
|
|
|
|
|
class RemediationVerificationCheck(BaseModel):
|
|
label: str
|
|
endpoint: str
|
|
expectedResult: str
|
|
source: str
|
|
readOnly: bool = True
|
|
|
|
|
|
class RemediationStep(BaseModel):
|
|
id: str
|
|
label: str
|
|
description: str
|
|
type: RemediationStepType
|
|
actionId: str | None = None
|
|
target: str | None = None
|
|
href: str | None = None
|
|
policyDecision: str = 'allowed'
|
|
risk: str = 'low'
|
|
requiresApproval: bool = False
|
|
canExecute: bool = False
|
|
evidence: list[RemediationEvidence] = Field(default_factory=list)
|
|
|
|
|
|
class RemediationPlan(BaseModel):
|
|
id: str
|
|
title: str
|
|
description: str
|
|
sourceType: RemediationSourceType
|
|
sourceId: str
|
|
severity: Severity
|
|
confidence: Confidence
|
|
status: RemediationPlanStatus = 'draft'
|
|
affectedResources: list[str] = Field(default_factory=list)
|
|
prerequisites: list[str] = Field(default_factory=list)
|
|
steps: list[RemediationStep] = Field(default_factory=list)
|
|
verificationChecks: list[RemediationVerificationCheck] = Field(default_factory=list)
|
|
blockedActions: list[RemediationStep] = Field(default_factory=list)
|
|
approvalRequirements: list[RemediationApprovalRequirement] = Field(default_factory=list)
|
|
riskAssessment: str
|
|
estimatedImpact: str
|
|
rollbackNotes: str
|
|
auditPreview: str
|
|
createdAt: str
|
|
updatedAt: str
|
|
executable: bool = False
|
|
|
|
|
|
class RemediationPlanCollection(BaseModel):
|
|
status: str
|
|
generatedAt: str
|
|
total: int
|
|
plans: list[RemediationPlan]
|
|
|
|
|
|
class RemediationDryRunStepResult(BaseModel):
|
|
stepId: str
|
|
label: str
|
|
actionId: str | None = None
|
|
target: str | None = None
|
|
policyDecision: str
|
|
risk: str
|
|
status: DryRunStatus
|
|
reason: str
|
|
canExecute: bool = False
|
|
|
|
|
|
class RemediationDryRunResult(BaseModel):
|
|
planId: str
|
|
status: DryRunStatus
|
|
executed: bool = False
|
|
reasons: list[str] = Field(default_factory=list)
|
|
prerequisites: list[str] = Field(default_factory=list)
|
|
unresolvedBlockers: list[str] = Field(default_factory=list)
|
|
blockedActions: list[RemediationApprovalRequirement] = Field(default_factory=list)
|
|
approvalRequirements: list[RemediationApprovalRequirement] = Field(default_factory=list)
|
|
verificationChecks: list[RemediationVerificationCheck] = Field(default_factory=list)
|
|
stepResults: list[RemediationDryRunStepResult] = Field(default_factory=list)
|
|
|
|
|
|
class RemediationApprovalProposal(BaseModel):
|
|
planId: str
|
|
created: bool
|
|
executed: bool = False
|
|
approvalId: str | None = None
|
|
proposals: list[RemediationApprovalRequirement] = Field(default_factory=list)
|
|
message: str
|