-
Notifications
You must be signed in to change notification settings - Fork 35
doc(adr): add ADR 00011 for CSAF remediation support #2179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Reviewer's GuideAdds a new architecture decision record (ADR 00011) defining how CSAF remediation guidance will be modeled, stored, ingested, and exposed via existing status APIs, including schema, ingestion flow, and query patterns. Sequence diagram for CSAF remediation ingestion flowsequenceDiagram
participant CsafIngestion as CsafIngestionService
participant StatusCreator as StatusCreator
participant ResolveCache as ResolveProductIdCache
participant RemediationCreator as RemediationCreator
participant DB as Database
CsafIngestion->>StatusCreator: create_status_records(csaf_document)
StatusCreator->>ResolveCache: resolve_product_ids(csaf_product_ids)
ResolveCache-->>StatusCreator: product_id_to_status_mapping
StatusCreator->>DB: insert_purl_status_records()
StatusCreator->>DB: insert_product_status_records()
StatusCreator-->>CsafIngestion: status_creation_result_with_mapping
CsafIngestion->>RemediationCreator: create_remediations(csaf_remediations, mapping)
RemediationCreator->>DB: insert_into_remediation(advisory_id, vulnerability_id, category, details, url, data)
RemediationCreator->>DB: insert_into_remediation_purl_status(remediation_id, purl_status_ids)
RemediationCreator->>DB: insert_into_remediation_product_status(remediation_id, product_status_ids)
RemediationCreator-->>CsafIngestion: remediation_creation_result
Sequence diagram for API status query with remediationssequenceDiagram
actor Client
participant Api as StatusApiService
participant DB as Database
Client->>Api: GET /v2/purl/{key}
Api->>DB: SELECT purl_status_with_remediations(purl_key)
DB-->>Api: purl_status_rows_with_joined_remediations
Api->>Api: map_rows_to_PurlStatus_and_RemediationSummary
Api-->>Client: PurlDetails_with_status_and_remediations
Client->>Api: POST /v3/vulnerability/analyze
Api->>DB: query_analysis_status_with_remediations(sbom_or_purls)
DB-->>Api: analysis_rows_with_remediations
Api->>Api: build_AnalysisResponse_with_PurlStatus_and_RemediationSummary
Api-->>Client: AnalysisResponse
ER diagram for CSAF remediation schema additionserDiagram
advisory_vulnerability {
UUID advisory_id
VARCHAR vulnerability_id
}
remediation {
UUID id
UUID advisory_id
VARCHAR vulnerability_id
VARCHAR category
TEXT details
VARCHAR url
JSONB data
}
purl_status {
UUID id
%% existing_columns
TEXT existing_columns
}
product_status {
UUID id
%% existing_columns
TEXT existing_columns
}
remediation_purl_status {
UUID remediation_id
UUID purl_status_id
}
remediation_product_status {
UUID remediation_id
UUID product_status_id
}
advisory_vulnerability ||--o{ remediation : has_remediation
remediation ||--o{ remediation_purl_status : links_purl_status
purl_status ||--o{ remediation_purl_status : is_target_of
remediation ||--o{ remediation_product_status : links_product_status
product_status ||--o{ remediation_product_status : is_target_of
Class diagram for remediation API models and status aggregationclassDiagram
class RemediationSummary {
Uuid id
String category
Option~String~ details
Option~String~ url
Option~JsonValue~ data
}
class PurlStatus {
/* existing_fields */
String status
String vulnerability_id
List~RemediationSummary~ remediations
}
class SbomStatus {
/* existing_fields */
String status
String vulnerability_id
List~RemediationSummary~ remediations
}
class PurlDetails {
/* existing_fields */
List~PurlStatus~ statuses
}
class SbomAdvisory {
/* existing_fields */
List~SbomStatus~ statuses
}
class AnalysisResponse {
/* existing_fields */
List~PurlStatus~ purl_statuses
}
PurlStatus "1" --> "*" RemediationSummary : has
SbomStatus "1" --> "*" RemediationSummary : has
PurlDetails "1" --> "*" PurlStatus : includes
SbomAdvisory "1" --> "*" SbomStatus : includes
AnalysisResponse "1" --> "*" PurlStatus : includes
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey there - I've reviewed your changes - here's some feedback:
- In the 'Related ADRs' and 'References' sections the Markdown link syntax is inverted, e.g.
(ADR 00008)[00008-purls-recommendation.md]; update these to[ADR 00008](00008-purls-recommendation.md)and similarly for the CSAF test data path so the links render correctly. - Consider clarifying in the ADR how conflicting or overlapping remediations will be handled when multiple advisories reference the same vulnerability/package pair (e.g., prioritization or deduplication rules), since the schema allows multiple remediation records to attach to the same status.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In the 'Related ADRs' and 'References' sections the Markdown link syntax is inverted, e.g. `(ADR 00008)[00008-purls-recommendation.md]`; update these to `[ADR 00008](00008-purls-recommendation.md)` and similarly for the CSAF test data path so the links render correctly.
- Consider clarifying in the ADR how conflicting or overlapping remediations will be handled when multiple advisories reference the same vulnerability/package pair (e.g., prioritization or deduplication rules), since the schema allows multiple remediation records to attach to the same status.
## Individual Comments
### Comment 1
<location> `docs/adrs/00011-csaf-remediation.md:93` </location>
<code_context>
+### Design Choices
+
+- Remediations link to **specific purl_status/product_status records**
+- Keep statuses (category) as VARCHAR. Having separate statuses table have added more complexity to queries than benefits.
+- Normalize only important remediation fields, while keeping the rest in JSON blob
+
</code_context>
<issue_to_address>
**suggestion (typo):** Fix subject–verb agreement in the explanation about a separate statuses table.
The sentence is grammatically off. Consider: "Having a separate statuses table would have added more complexity to queries than benefits" or "Having a separate statuses table has added more complexity to queries than benefits," depending on the tense you want.
```suggestion
- Remediations link to **specific purl_status/product_status records**
- Keep statuses (category) as VARCHAR. Having a separate statuses table has added more complexity to queries than benefits.
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Propose ingesting CSAF remediation guidance and exposing it via APIs. Remediations provide actionable guidance (upgrade paths, workarounds) alongside vulnerability status information. Assisted-by: Claude Signed-off-by: Dejan Bosanac <[email protected]>
212e80e to
e3960a2
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2179 +/- ##
=======================================
Coverage 68.22% 68.23%
=======================================
Files 376 376
Lines 21190 21190
Branches 21190 21190
=======================================
+ Hits 14456 14458 +2
+ Misses 5868 5862 -6
- Partials 866 870 +4 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| - **URL**: Link to detailed guidance | ||
| - **Metadata**: Restart requirements, dates, entitlements | ||
|
|
||
| Critically, remediation `product_ids` often overlap with `product_status` product_ids (e.g., vendor_fix applies to the same products marked as "fixed"). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is a RH issue. And not a common practice. I might be wrong, but to my understanding this isn't allowed right now (in the spec) and will be specifically forbidden in the upcoming 2.1 spec. So I think we should not design for this.
| #[derive(Serialize, Deserialize, Debug, Clone, ToSchema)] | ||
| pub struct RemediationSummary { | ||
| pub id: Uuid, | ||
| pub category: String, // vendor_fix, workaround, mitigation, etc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd love to see this as a enum. Even in the database.
| pub category: String, // vendor_fix, workaround, mitigation, etc. | ||
| pub details: Option<String>, | ||
| pub url: Option<String>, | ||
| pub data: Option<serde_json::Value>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe have this as Value only. As it already supports Value::Null.
|
|
||
| **Modified Response Structures:** | ||
|
|
||
| Add `remediations: Vec<RemediationSummary>` to: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know we did simply add new information to all existing fields in the past. But is that the right idea? Why not start by adding it to the endpoints that require it today.
| "status": "affected", | ||
| "remediations": [ | ||
| { | ||
| "id": "550e8400-e29b-41d4-a716-446655440000", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like an internal ID, does it make sense for the user to have it?
Propose ingesting CSAF remediation guidance and exposing it via APIs. Remediations provide actionable guidance (upgrade paths, workarounds) alongside vulnerability status information.
Assisted-by: Claude
Summary by Sourcery
Documentation: