Skip to content

Commit e77d48f

Browse files
Add incident review and supply chain metadata
1 parent acc72e7 commit e77d48f

6 files changed

Lines changed: 1694 additions & 7 deletions

File tree

rust/iscy-backend/src/asset_store.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ pub struct InformationAssetSummary {
3333
pub availability: String,
3434
pub lifecycle_status: String,
3535
pub is_in_scope: bool,
36+
pub cpe23_uri: String,
37+
pub package_url: String,
38+
pub sbom_document_url: String,
39+
pub software_inventory_ref: String,
3640
pub created_at: String,
3741
pub updated_at: String,
3842
}
@@ -102,6 +106,10 @@ async fn list_information_assets_postgres(
102106
asset.availability,
103107
asset.lifecycle_status,
104108
asset.is_in_scope,
109+
asset.cpe23_uri,
110+
asset.package_url,
111+
asset.sbom_document_url,
112+
asset.software_inventory_ref,
105113
asset.created_at::text AS created_at,
106114
asset.updated_at::text AS updated_at
107115
FROM assets_app_informationasset asset
@@ -152,6 +160,10 @@ async fn list_information_assets_sqlite(
152160
asset.availability,
153161
asset.lifecycle_status,
154162
asset.is_in_scope,
163+
asset.cpe23_uri,
164+
asset.package_url,
165+
asset.sbom_document_url,
166+
asset.software_inventory_ref,
155167
CAST(asset.created_at AS TEXT) AS created_at,
156168
CAST(asset.updated_at AS TEXT) AS updated_at
157169
FROM assets_app_informationasset asset
@@ -197,6 +209,10 @@ fn summary_from_pg_row(row: PgRow) -> Result<InformationAssetSummary, sqlx::Erro
197209
availability: row.try_get("availability")?,
198210
lifecycle_status: row.try_get("lifecycle_status")?,
199211
is_in_scope: row.try_get("is_in_scope")?,
212+
cpe23_uri: row.try_get("cpe23_uri")?,
213+
package_url: row.try_get("package_url")?,
214+
sbom_document_url: row.try_get("sbom_document_url")?,
215+
software_inventory_ref: row.try_get("software_inventory_ref")?,
200216
created_at: row.try_get("created_at")?,
201217
updated_at: row.try_get("updated_at")?,
202218
})
@@ -223,6 +239,10 @@ fn summary_from_sqlite_row(row: SqliteRow) -> Result<InformationAssetSummary, sq
223239
availability: row.try_get("availability")?,
224240
lifecycle_status: row.try_get("lifecycle_status")?,
225241
is_in_scope: row.try_get("is_in_scope")?,
242+
cpe23_uri: row.try_get("cpe23_uri")?,
243+
package_url: row.try_get("package_url")?,
244+
sbom_document_url: row.try_get("sbom_document_url")?,
245+
software_inventory_ref: row.try_get("software_inventory_ref")?,
226246
created_at: row.try_get("created_at")?,
227247
updated_at: row.try_get("updated_at")?,
228248
})

rust/iscy-backend/src/db_admin.rs

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ const MIGRATIONS: &[Migration] = &[
9797
sqlite_sql: SQLITE_INCIDENT_RUNBOOK_TASK_TIMELINE_MARKER_SCHEMA,
9898
postgres_sql: POSTGRES_INCIDENT_RUNBOOK_TASK_TIMELINE_MARKER_SCHEMA,
9999
},
100+
Migration {
101+
version: "0014_rust_review_supply_chain_metadata",
102+
sqlite_sql: SQLITE_REVIEW_SUPPLY_CHAIN_METADATA_SCHEMA,
103+
postgres_sql: POSTGRES_REVIEW_SUPPLY_CHAIN_METADATA_SCHEMA,
104+
},
100105
];
101106

102107
const SQLITE_CATALOG_REQUIREMENTS_SEED: &str =
@@ -694,6 +699,160 @@ CREATE INDEX IF NOT EXISTS idx_incident_runbook_steps_done
694699
ON incidents_runbookstep(tenant_id, incident_id, is_done);
695700
"#;
696701

702+
const SQLITE_REVIEW_SUPPLY_CHAIN_METADATA_SCHEMA: &str = r#"
703+
ALTER TABLE incidents_incident ADD COLUMN review_state varchar(24) NOT NULL DEFAULT 'DRAFT';
704+
ALTER TABLE incidents_incident ADD COLUMN reviewed_by_id INTEGER NULL;
705+
ALTER TABLE incidents_incident ADD COLUMN reviewed_at TEXT NULL;
706+
ALTER TABLE incidents_incident ADD COLUMN review_notes TEXT NOT NULL DEFAULT '';
707+
ALTER TABLE incidents_incident ADD COLUMN approved_by_id INTEGER NULL;
708+
ALTER TABLE incidents_incident ADD COLUMN approved_at TEXT NULL;
709+
ALTER TABLE incidents_incident ADD COLUMN approval_notes TEXT NOT NULL DEFAULT '';
710+
ALTER TABLE incidents_incident ADD COLUMN report_package_version varchar(32) NOT NULL DEFAULT '1.0';
711+
CREATE INDEX IF NOT EXISTS idx_incidents_review_state
712+
ON incidents_incident(tenant_id, review_state, updated_at);
713+
714+
ALTER TABLE assets_app_informationasset ADD COLUMN cpe23_uri TEXT NOT NULL DEFAULT '';
715+
ALTER TABLE assets_app_informationasset ADD COLUMN package_url TEXT NOT NULL DEFAULT '';
716+
ALTER TABLE assets_app_informationasset ADD COLUMN sbom_document_url TEXT NOT NULL DEFAULT '';
717+
ALTER TABLE assets_app_informationasset ADD COLUMN software_inventory_ref TEXT NOT NULL DEFAULT '';
718+
CREATE INDEX IF NOT EXISTS idx_assets_cpe
719+
ON assets_app_informationasset(tenant_id, cpe23_uri);
720+
721+
ALTER TABLE product_security_component ADD COLUMN cpe23_uri varchar(255) NOT NULL DEFAULT '';
722+
ALTER TABLE product_security_component ADD COLUMN package_url TEXT NOT NULL DEFAULT '';
723+
ALTER TABLE product_security_component ADD COLUMN sbom_format varchar(32) NOT NULL DEFAULT '';
724+
ALTER TABLE product_security_component ADD COLUMN sbom_document_url TEXT NOT NULL DEFAULT '';
725+
ALTER TABLE product_security_component ADD COLUMN sbom_digest varchar(128) NOT NULL DEFAULT '';
726+
ALTER TABLE product_security_component ADD COLUMN sbom_generated_at TEXT NULL;
727+
CREATE INDEX IF NOT EXISTS idx_product_security_component_cpe
728+
ON product_security_component(tenant_id, cpe23_uri);
729+
CREATE INDEX IF NOT EXISTS idx_product_security_component_purl
730+
ON product_security_component(tenant_id, package_url);
731+
732+
ALTER TABLE product_security_vulnerability ADD COLUMN cpe23_uri varchar(255) NOT NULL DEFAULT '';
733+
ALTER TABLE product_security_vulnerability ADD COLUMN advisory_ids_json TEXT NOT NULL DEFAULT '[]';
734+
CREATE INDEX IF NOT EXISTS idx_product_security_vulnerability_cpe
735+
ON product_security_vulnerability(tenant_id, cpe23_uri);
736+
737+
ALTER TABLE product_security_securityadvisory ADD COLUMN csaf_url TEXT NOT NULL DEFAULT '';
738+
ALTER TABLE product_security_securityadvisory ADD COLUMN csaf_document_id varchar(128) NOT NULL DEFAULT '';
739+
ALTER TABLE product_security_securityadvisory ADD COLUMN csaf_profile varchar(64) NOT NULL DEFAULT '';
740+
ALTER TABLE product_security_securityadvisory ADD COLUMN csaf_tracking_status varchar(32) NOT NULL DEFAULT '';
741+
ALTER TABLE product_security_securityadvisory ADD COLUMN csaf_revision varchar(32) NOT NULL DEFAULT '';
742+
ALTER TABLE product_security_securityadvisory ADD COLUMN cve_list_json TEXT NOT NULL DEFAULT '[]';
743+
ALTER TABLE product_security_securityadvisory ADD COLUMN product_status_json TEXT NOT NULL DEFAULT '{}';
744+
CREATE INDEX IF NOT EXISTS idx_product_security_advisory_csaf
745+
ON product_security_securityadvisory(tenant_id, csaf_document_id);
746+
747+
UPDATE assets_app_informationasset
748+
SET
749+
cpe23_uri = CASE WHEN name = 'Customer Portal' THEN 'cpe:2.3:a:iscy:customer_portal:1.0:*:*:*:*:*:*:*' ELSE cpe23_uri END,
750+
package_url = CASE WHEN name = 'Customer Portal' THEN 'pkg:generic/iscy/customer-portal@1.0' ELSE package_url END,
751+
sbom_document_url = CASE WHEN name = 'Customer Portal' THEN 'file://evidence/sbom/customer-portal.cdx.json' ELSE sbom_document_url END,
752+
software_inventory_ref = CASE WHEN name = 'Customer Portal' THEN 'ISCY-ASSET-PORTAL-1' ELSE software_inventory_ref END;
753+
754+
UPDATE product_security_component
755+
SET
756+
cpe23_uri = CASE WHEN name = 'Gateway Firmware' THEN 'cpe:2.3:o:iscy:sensor_gateway_firmware:1.0.3:*:*:*:*:*:*:*' ELSE cpe23_uri END,
757+
package_url = CASE WHEN name = 'Gateway Firmware' THEN 'pkg:generic/iscy/sensor-gateway-firmware@1.0.3' ELSE package_url END,
758+
sbom_format = CASE WHEN name = 'Gateway Firmware' THEN 'CycloneDX' ELSE sbom_format END,
759+
sbom_document_url = CASE WHEN name = 'Gateway Firmware' THEN 'file://evidence/sbom/sensor-gateway-1.0.3.cdx.json' ELSE sbom_document_url END,
760+
sbom_digest = CASE WHEN name = 'Gateway Firmware' THEN 'sha256:demo-sbom-digest' ELSE sbom_digest END,
761+
sbom_generated_at = CASE WHEN name = 'Gateway Firmware' THEN '2026-04-18T10:30:00Z' ELSE sbom_generated_at END;
762+
763+
UPDATE product_security_vulnerability
764+
SET
765+
cpe23_uri = CASE WHEN cve = 'CVE-2026-0001' THEN 'cpe:2.3:o:iscy:sensor_gateway_firmware:1.0.3:*:*:*:*:*:*:*' ELSE cpe23_uri END,
766+
advisory_ids_json = CASE WHEN cve = 'CVE-2026-0001' THEN '["ADV-1"]' ELSE advisory_ids_json END;
767+
768+
UPDATE product_security_securityadvisory
769+
SET
770+
csaf_url = CASE WHEN advisory_id = 'ADV-1' THEN 'https://example.invalid/.well-known/csaf/iscy-2026-adv-1.json' ELSE csaf_url END,
771+
csaf_document_id = CASE WHEN advisory_id = 'ADV-1' THEN 'ISCY-2026-ADV-1' ELSE csaf_document_id END,
772+
csaf_profile = CASE WHEN advisory_id = 'ADV-1' THEN 'Security Advisory' ELSE csaf_profile END,
773+
csaf_tracking_status = CASE WHEN advisory_id = 'ADV-1' THEN 'final' ELSE csaf_tracking_status END,
774+
csaf_revision = CASE WHEN advisory_id = 'ADV-1' THEN '1' ELSE csaf_revision END,
775+
cve_list_json = CASE WHEN advisory_id = 'ADV-1' THEN '["CVE-2026-0001"]' ELSE cve_list_json END,
776+
product_status_json = CASE WHEN advisory_id = 'ADV-1' THEN '{"known_affected":["sensor-gateway-firmware-1.0.3"],"fixed":["sensor-gateway-firmware-1.0.4"]}' ELSE product_status_json END;
777+
"#;
778+
779+
const POSTGRES_REVIEW_SUPPLY_CHAIN_METADATA_SCHEMA: &str = r#"
780+
ALTER TABLE incidents_incident ADD COLUMN IF NOT EXISTS review_state varchar(24) NOT NULL DEFAULT 'DRAFT';
781+
ALTER TABLE incidents_incident ADD COLUMN IF NOT EXISTS reviewed_by_id BIGINT NULL;
782+
ALTER TABLE incidents_incident ADD COLUMN IF NOT EXISTS reviewed_at TEXT NULL;
783+
ALTER TABLE incidents_incident ADD COLUMN IF NOT EXISTS review_notes TEXT NOT NULL DEFAULT '';
784+
ALTER TABLE incidents_incident ADD COLUMN IF NOT EXISTS approved_by_id BIGINT NULL;
785+
ALTER TABLE incidents_incident ADD COLUMN IF NOT EXISTS approved_at TEXT NULL;
786+
ALTER TABLE incidents_incident ADD COLUMN IF NOT EXISTS approval_notes TEXT NOT NULL DEFAULT '';
787+
ALTER TABLE incidents_incident ADD COLUMN IF NOT EXISTS report_package_version varchar(32) NOT NULL DEFAULT '1.0';
788+
CREATE INDEX IF NOT EXISTS idx_incidents_review_state
789+
ON incidents_incident(tenant_id, review_state, updated_at);
790+
791+
ALTER TABLE assets_app_informationasset ADD COLUMN IF NOT EXISTS cpe23_uri TEXT NOT NULL DEFAULT '';
792+
ALTER TABLE assets_app_informationasset ADD COLUMN IF NOT EXISTS package_url TEXT NOT NULL DEFAULT '';
793+
ALTER TABLE assets_app_informationasset ADD COLUMN IF NOT EXISTS sbom_document_url TEXT NOT NULL DEFAULT '';
794+
ALTER TABLE assets_app_informationasset ADD COLUMN IF NOT EXISTS software_inventory_ref TEXT NOT NULL DEFAULT '';
795+
CREATE INDEX IF NOT EXISTS idx_assets_cpe
796+
ON assets_app_informationasset(tenant_id, cpe23_uri);
797+
798+
ALTER TABLE product_security_component ADD COLUMN IF NOT EXISTS cpe23_uri varchar(255) NOT NULL DEFAULT '';
799+
ALTER TABLE product_security_component ADD COLUMN IF NOT EXISTS package_url TEXT NOT NULL DEFAULT '';
800+
ALTER TABLE product_security_component ADD COLUMN IF NOT EXISTS sbom_format varchar(32) NOT NULL DEFAULT '';
801+
ALTER TABLE product_security_component ADD COLUMN IF NOT EXISTS sbom_document_url TEXT NOT NULL DEFAULT '';
802+
ALTER TABLE product_security_component ADD COLUMN IF NOT EXISTS sbom_digest varchar(128) NOT NULL DEFAULT '';
803+
ALTER TABLE product_security_component ADD COLUMN IF NOT EXISTS sbom_generated_at TEXT NULL;
804+
CREATE INDEX IF NOT EXISTS idx_product_security_component_cpe
805+
ON product_security_component(tenant_id, cpe23_uri);
806+
CREATE INDEX IF NOT EXISTS idx_product_security_component_purl
807+
ON product_security_component(tenant_id, package_url);
808+
809+
ALTER TABLE product_security_vulnerability ADD COLUMN IF NOT EXISTS cpe23_uri varchar(255) NOT NULL DEFAULT '';
810+
ALTER TABLE product_security_vulnerability ADD COLUMN IF NOT EXISTS advisory_ids_json TEXT NOT NULL DEFAULT '[]';
811+
CREATE INDEX IF NOT EXISTS idx_product_security_vulnerability_cpe
812+
ON product_security_vulnerability(tenant_id, cpe23_uri);
813+
814+
ALTER TABLE product_security_securityadvisory ADD COLUMN IF NOT EXISTS csaf_url TEXT NOT NULL DEFAULT '';
815+
ALTER TABLE product_security_securityadvisory ADD COLUMN IF NOT EXISTS csaf_document_id varchar(128) NOT NULL DEFAULT '';
816+
ALTER TABLE product_security_securityadvisory ADD COLUMN IF NOT EXISTS csaf_profile varchar(64) NOT NULL DEFAULT '';
817+
ALTER TABLE product_security_securityadvisory ADD COLUMN IF NOT EXISTS csaf_tracking_status varchar(32) NOT NULL DEFAULT '';
818+
ALTER TABLE product_security_securityadvisory ADD COLUMN IF NOT EXISTS csaf_revision varchar(32) NOT NULL DEFAULT '';
819+
ALTER TABLE product_security_securityadvisory ADD COLUMN IF NOT EXISTS cve_list_json TEXT NOT NULL DEFAULT '[]';
820+
ALTER TABLE product_security_securityadvisory ADD COLUMN IF NOT EXISTS product_status_json TEXT NOT NULL DEFAULT '{}';
821+
CREATE INDEX IF NOT EXISTS idx_product_security_advisory_csaf
822+
ON product_security_securityadvisory(tenant_id, csaf_document_id);
823+
824+
UPDATE assets_app_informationasset
825+
SET
826+
cpe23_uri = CASE WHEN name = 'Customer Portal' THEN 'cpe:2.3:a:iscy:customer_portal:1.0:*:*:*:*:*:*:*' ELSE cpe23_uri END,
827+
package_url = CASE WHEN name = 'Customer Portal' THEN 'pkg:generic/iscy/customer-portal@1.0' ELSE package_url END,
828+
sbom_document_url = CASE WHEN name = 'Customer Portal' THEN 'file://evidence/sbom/customer-portal.cdx.json' ELSE sbom_document_url END,
829+
software_inventory_ref = CASE WHEN name = 'Customer Portal' THEN 'ISCY-ASSET-PORTAL-1' ELSE software_inventory_ref END;
830+
831+
UPDATE product_security_component
832+
SET
833+
cpe23_uri = CASE WHEN name = 'Gateway Firmware' THEN 'cpe:2.3:o:iscy:sensor_gateway_firmware:1.0.3:*:*:*:*:*:*:*' ELSE cpe23_uri END,
834+
package_url = CASE WHEN name = 'Gateway Firmware' THEN 'pkg:generic/iscy/sensor-gateway-firmware@1.0.3' ELSE package_url END,
835+
sbom_format = CASE WHEN name = 'Gateway Firmware' THEN 'CycloneDX' ELSE sbom_format END,
836+
sbom_document_url = CASE WHEN name = 'Gateway Firmware' THEN 'file://evidence/sbom/sensor-gateway-1.0.3.cdx.json' ELSE sbom_document_url END,
837+
sbom_digest = CASE WHEN name = 'Gateway Firmware' THEN 'sha256:demo-sbom-digest' ELSE sbom_digest END,
838+
sbom_generated_at = CASE WHEN name = 'Gateway Firmware' THEN '2026-04-18T10:30:00Z' ELSE sbom_generated_at END;
839+
840+
UPDATE product_security_vulnerability
841+
SET
842+
cpe23_uri = CASE WHEN cve = 'CVE-2026-0001' THEN 'cpe:2.3:o:iscy:sensor_gateway_firmware:1.0.3:*:*:*:*:*:*:*' ELSE cpe23_uri END,
843+
advisory_ids_json = CASE WHEN cve = 'CVE-2026-0001' THEN '["ADV-1"]' ELSE advisory_ids_json END;
844+
845+
UPDATE product_security_securityadvisory
846+
SET
847+
csaf_url = CASE WHEN advisory_id = 'ADV-1' THEN 'https://example.invalid/.well-known/csaf/iscy-2026-adv-1.json' ELSE csaf_url END,
848+
csaf_document_id = CASE WHEN advisory_id = 'ADV-1' THEN 'ISCY-2026-ADV-1' ELSE csaf_document_id END,
849+
csaf_profile = CASE WHEN advisory_id = 'ADV-1' THEN 'Security Advisory' ELSE csaf_profile END,
850+
csaf_tracking_status = CASE WHEN advisory_id = 'ADV-1' THEN 'final' ELSE csaf_tracking_status END,
851+
csaf_revision = CASE WHEN advisory_id = 'ADV-1' THEN '1' ELSE csaf_revision END,
852+
cve_list_json = CASE WHEN advisory_id = 'ADV-1' THEN '["CVE-2026-0001"]' ELSE cve_list_json END,
853+
product_status_json = CASE WHEN advisory_id = 'ADV-1' THEN '{"known_affected":["sensor-gateway-firmware-1.0.3"],"fixed":["sensor-gateway-firmware-1.0.4"]}' ELSE product_status_json END;
854+
"#;
855+
697856
const SQLITE_AUTH_RBAC_SCHEMA: &str = r#"
698857
CREATE TABLE IF NOT EXISTS accounts_role (
699858
id INTEGER PRIMARY KEY AUTOINCREMENT,

0 commit comments

Comments
 (0)