Skip to content

Commit 1a62930

Browse files
committed
test: add tests for SBOMs
1 parent 8342c2e commit 1a62930

File tree

5 files changed

+129
-62
lines changed

5 files changed

+129
-62
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

etc/deploy/compose/compose.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ services:
1010
shm_size: '1g'
1111
command: >
1212
postgres -c random_page_cost=1.1 -c max_parallel_workers_per_gather=4 -c shared_preload_libraries='pg_stat_statements'
13+
volumes:
14+
- /home/jreimann/Downloads/trustify/dump.sql.gz:/docker-entrypoint-initdb.d/dump-20250604T002104Z.sql.gz:Z

modules/fundamental/tests/signature/mod.rs

Lines changed: 123 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,23 @@
1-
use crate::caller;
2-
use crate::common::create_zip;
1+
use crate::{caller, common::create_zip};
32
use actix_http::StatusCode;
43
use actix_web::test::{TestRequest, read_body_json};
5-
use base64::Engine;
6-
use base64::engine::general_purpose::STANDARD;
4+
use base64::{Engine, engine::general_purpose::STANDARD};
75
use serde_json::{Value, json};
86
use test_context::test_context;
97
use test_log::test;
8+
use trustify_module_ingestor::service::dataset::DatasetIngestResult;
9+
use trustify_module_signature::service::DocumentType;
1010
use trustify_test_context::{TrustifyContext, call::CallService, document_bytes};
1111
use urlencoding::encode;
1212

13-
#[test_context(TrustifyContext)]
14-
#[test(tokio::test)]
15-
async fn simple(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
16-
let app = caller(ctx).await?;
17-
18-
// create zip and ingest (ds6 has signatures)
19-
20-
let sig = document_bytes("../datasets/ds6/csaf/2022/cve-2022-45787.json.asc").await?;
21-
let trust_anchor = document_bytes("trust_anchor/97f5eac4.txt").await?;
22-
23-
let data = create_zip(ctx.absolute_path("../datasets/ds6")?)?;
24-
let result = ctx.ingestor.ingest_dataset(&data, (), 0).await?;
25-
26-
let id = result.files["csaf/2022/cve-2022-45787.json"].id.to_string();
27-
28-
// get the signatures
29-
13+
async fn ensure_one_signature(
14+
app: &impl CallService,
15+
r#type: DocumentType,
16+
id: &str,
17+
signature: &[u8],
18+
) {
3019
let request = TestRequest::get()
31-
.uri(&format!("/api/v2/advisory/{}/signature", encode(&id)))
20+
.uri(&format!("/api/v2/{type}/{}/signature", encode(id)))
3221
.to_request();
3322

3423
let response = app.call_service(request).await;
@@ -43,16 +32,22 @@ async fn simple(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
4332
{
4433
"id": result["items"][0]["id"].clone(),
4534
"type": "pgp",
46-
"payload": STANDARD.encode(&sig),
35+
"payload": STANDARD.encode(signature),
4736
}
4837
]
4938
})
5039
);
40+
}
5141

52-
// verify (without trust anchors)
53-
42+
async fn ensure_valid_signature(
43+
app: &impl CallService,
44+
r#type: DocumentType,
45+
id: &str,
46+
signature: &[u8],
47+
expected_trust_anchors: Value,
48+
) {
5449
let request = TestRequest::get()
55-
.uri(&format!("/api/v2/advisory/{}/verify", encode(&id)))
50+
.uri(&format!("/api/v2/{type}/{}/verify", encode(id)))
5651
.to_request();
5752
let response = app.call_service(request).await;
5853
assert_eq!(response.status(), StatusCode::OK);
@@ -65,59 +60,126 @@ async fn simple(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
6560
"signature": {
6661
"id": result["items"][0]["signature"]["id"].clone(),
6762
"type": "pgp",
68-
"payload": STANDARD.encode(&sig),
63+
"payload": STANDARD.encode(signature),
6964
},
70-
"trustAnchors": []
65+
"trustAnchors": expected_trust_anchors
7166
}
7267
],
7368
"total": 1,
7469
})
7570
);
71+
}
7672

77-
// add a matching trust anchor
78-
73+
async fn add_trust_anchor(app: &impl CallService, trust_anchor: &[u8]) {
7974
let request = TestRequest::post()
8075
.uri("/api/v2/trust-anchor/test")
8176
.set_json(json!({
8277
"type": "pgp",
83-
"payload": STANDARD.encode(&trust_anchor),
78+
"payload": STANDARD.encode(trust_anchor),
8479
}))
8580
.to_request();
8681
let response = app.call_service(request).await;
8782
assert_eq!(response.status(), StatusCode::CREATED);
83+
}
84+
85+
async fn ingest_ds6(ctx: &TrustifyContext) -> anyhow::Result<DatasetIngestResult> {
86+
let data = create_zip(ctx.absolute_path("../datasets/ds6")?)?;
87+
let result = ctx.ingestor.ingest_dataset(&data, (), 0).await?;
88+
89+
Ok(result)
90+
}
91+
92+
#[test_context(TrustifyContext)]
93+
#[test(tokio::test)]
94+
async fn simple_advisory(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
95+
let app = caller(ctx).await?;
96+
97+
// create zip and ingest (ds6 has signatures)
98+
99+
let result = ingest_ds6(ctx).await?;
100+
101+
// get data
102+
103+
let trust_anchor = document_bytes("trust_anchor/97f5eac4.txt").await?;
104+
let sig = document_bytes("../datasets/ds6/csaf/2022/cve-2022-45787.json.asc").await?;
105+
let id = result.files["csaf/2022/cve-2022-45787.json"].id.to_string();
106+
107+
// get the signatures
108+
109+
ensure_one_signature(&app, DocumentType::Advisory, &id, &sig).await;
110+
111+
// verify (without trust anchors)
112+
113+
ensure_valid_signature(&app, DocumentType::Advisory, &id, &sig, json!([])).await;
114+
115+
// add a matching trust anchor
116+
117+
add_trust_anchor(&app, &trust_anchor).await;
88118

89119
// verify (with a matching trust anchor)
90120

91-
let request = TestRequest::get()
92-
.uri(&format!("/api/v2/advisory/{}/verify", encode(&id)))
93-
.to_request();
94-
let response = app.call_service(request).await;
95-
assert_eq!(response.status(), StatusCode::OK);
96-
let result: Value = read_body_json(response).await;
97-
assert_eq!(
98-
result,
99-
json!({
100-
"items": [
101-
{
102-
"signature": {
103-
"id": result["items"][0]["signature"]["id"].clone(),
104-
"type": "pgp",
105-
"payload": STANDARD.encode(&sig),
106-
},
107-
"trustAnchors": [
108-
{
109-
"id": "test",
110-
"type": "pgp",
111-
"disabled": false,
112-
"description": "",
113-
"payload": STANDARD.encode(&trust_anchor),
114-
}
115-
]
116-
}
117-
],
118-
"total": 1,
119-
})
120-
);
121+
ensure_valid_signature(
122+
&app,
123+
DocumentType::Advisory,
124+
&id,
125+
&sig,
126+
json!([{
127+
"id": "test",
128+
"type": "pgp",
129+
"disabled": false,
130+
"description": "",
131+
"payload": STANDARD.encode(&trust_anchor),
132+
}]),
133+
)
134+
.await;
135+
136+
// done
137+
138+
Ok(())
139+
}
140+
141+
#[test_context(TrustifyContext)]
142+
#[test(tokio::test)]
143+
async fn simple_sbom(ctx: &TrustifyContext) -> Result<(), anyhow::Error> {
144+
let app = caller(ctx).await?;
145+
146+
// create zip and ingest (ds6 has signatures)
147+
148+
let result = ingest_ds6(ctx).await?;
149+
150+
// get data
151+
152+
let trust_anchor = document_bytes("trust_anchor/97f5eac4.txt").await?;
153+
let sig =
154+
document_bytes("../datasets/ds6/spdx/quarkus-bom-2.13.8.Final-redhat-00004.json.bz2.asc")
155+
.await?;
156+
let id = result.files["spdx/quarkus-bom-2.13.8.Final-redhat-00004.json.bz2"]
157+
.id
158+
.to_string();
159+
160+
// get the signatures
161+
162+
ensure_one_signature(&app, DocumentType::Sbom, &id, &sig).await;
163+
164+
// verify (without trust anchors)
165+
166+
ensure_valid_signature(&app, DocumentType::Sbom, &id, &sig, json!([])).await;
167+
168+
// add a matching trust anchor
169+
170+
add_trust_anchor(&app, &trust_anchor).await;
171+
172+
// verify (with a matching trust anchor)
173+
174+
ensure_valid_signature(
175+
&app,
176+
DocumentType::Sbom,
177+
&id,
178+
&sig,
179+
// we don't expect a valid signature here, since the signature is for the compressed file
180+
json!([]),
181+
)
182+
.await;
121183

122184
// done
123185

modules/signature/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ sequoia-openpgp = { workspace = true }
2222
serde = { workspace = true }
2323
serde_json = { workspace = true }
2424
serde_with = { workspace = true }
25+
strum= { workspace = true, features = ["derive"] }
2526
tempfile = { workspace = true }
2627
thiserror = { workspace = true }
2728
tokio = { workspace = true }

modules/signature/src/service/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use sea_orm::{ConnectionTrait, EntityTrait, QueryFilter};
99
use trustify_common::id::{Id, TryFilterForId};
1010
use trustify_entity::{advisory, sbom, source_document};
1111

12-
#[derive(Copy, Clone, Eq, PartialEq)]
12+
#[derive(Copy, Clone, Eq, PartialEq, strum::Display)]
13+
#[strum(serialize_all = "lowercase")]
1314
pub enum DocumentType {
1415
Advisory,
1516
Sbom,

0 commit comments

Comments
 (0)