Skip to content

Commit 2bef27f

Browse files
committed
trustee: Add unit tests
Tested functions: - sync_all_machine_luks_key - update_attestation_keys Signed-off-by: Roy Kaufman <rkaufman@redhat.com>
1 parent b98c589 commit 2bef27f

4 files changed

Lines changed: 226 additions & 8 deletions

File tree

Cargo.lock

Lines changed: 40 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

operator/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ toml = "1.1.2"
3434
kbs-client = {git = "https://github.com/confidential-containers/trustee.git", rev = "e65897a9ad4eb3ac69fa2ec75ed831200eb2acd7", default-features = false, features = ["native-tls"] }
3535
jsonwebtoken = { version = "10.4.0", default-features = false, features = ["use_pem"] }
3636
jsonwebtoken-openssl = "1.0.0"
37+
jiff = "0.2.29"
3738

3839
[dev-dependencies]
3940
http.workspace = true

operator/src/test_utils.rs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22
//
33
// SPDX-License-Identifier: MIT
44

5+
use crate::trustee;
56
use compute_pcrs_lib::Pcr;
7+
use k8s_openapi::apimachinery::pkg::apis::meta::v1::OwnerReference;
68
use k8s_openapi::{
79
api::core::v1::{ConfigMap, Secret},
810
jiff::Timestamp,
911
};
12+
use kube::api::ObjectMeta;
1013
use std::collections::BTreeMap;
11-
12-
use crate::trustee;
1314
use trusted_cluster_operator_lib::reference_values::{ImagePcr, ImagePcrs, PCR_CONFIG_FILE};
15+
use trusted_cluster_operator_lib::{Machine, MachineSpec};
1416

1517
pub fn dummy_pcrs() -> ImagePcrs {
1618
ImagePcrs(BTreeMap::from([(
@@ -74,3 +76,45 @@ pub fn dummy_pcrs_map() -> ConfigMap {
7476
..Default::default()
7577
}
7678
}
79+
80+
pub fn dummy_machine(id: &str) -> Machine {
81+
Machine {
82+
metadata: ObjectMeta {
83+
name: Some(id.to_string()),
84+
..Default::default()
85+
},
86+
spec: MachineSpec { id: id.to_string() },
87+
status: None,
88+
}
89+
}
90+
91+
pub fn dummy_secret() -> Secret {
92+
let data = BTreeMap::from([(
93+
"root".to_string(),
94+
k8s_openapi::ByteString(b"secret-data".to_vec()),
95+
)]);
96+
Secret {
97+
data: Some(data),
98+
..Default::default()
99+
}
100+
}
101+
102+
pub fn dummy_ak_secret(name: &str) -> Secret {
103+
Secret {
104+
metadata: ObjectMeta {
105+
name: Some(name.to_string()),
106+
owner_references: Some(vec![OwnerReference {
107+
kind: "AttestationKey".to_string(),
108+
name: name.to_string(),
109+
uid: "ak-uid".to_string(),
110+
..Default::default()
111+
}]),
112+
..Default::default()
113+
},
114+
data: Some(BTreeMap::from([(
115+
"public_key".to_string(),
116+
k8s_openapi::ByteString(b"test-ak-public-key".to_vec()),
117+
)])),
118+
..Default::default()
119+
}
120+
}

operator/src/trustee.rs

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,4 +919,143 @@ mod tests {
919919
assert_eq!(rv.version, "0.1.0");
920920
}
921921
}
922+
923+
#[tokio::test]
924+
async fn test_sync_all_machine_luks_key_empty() {
925+
let clos = async |req: Request<_>, ctr| match (ctr, req.method()) {
926+
(0, &Method::GET) => {
927+
let list = kube::api::ObjectList {
928+
items: Vec::<Machine>::new(),
929+
types: Default::default(),
930+
metadata: Default::default(),
931+
};
932+
Ok(serde_json::to_string(&list).unwrap())
933+
}
934+
_ => panic!("unexpected API interaction: {req:?}, counter {ctr}"),
935+
};
936+
count_check!(1, clos, |client| {
937+
assert!(sync_all_machine_luks_key(client).await.is_ok());
938+
});
939+
}
940+
941+
#[tokio::test]
942+
async fn test_sync_all_machine_luks_key_send_success() {
943+
let _ = jsonwebtoken_openssl::install_default();
944+
let clos = async |req: Request<_>, ctr| match (ctr, req.method()) {
945+
(0, &Method::GET) => {
946+
let list = kube::api::ObjectList {
947+
items: vec![dummy_machine("m1"), dummy_machine("m2")],
948+
types: Default::default(),
949+
metadata: Default::default(),
950+
};
951+
Ok(serde_json::to_string(&list).unwrap())
952+
}
953+
(1, &Method::GET) => {
954+
assert!(req.uri().path().contains(TRUSTEE_AUTH_SECRET));
955+
Ok(serde_json::to_string(&dummy_trustee_auth()).unwrap())
956+
}
957+
(2, &Method::GET) => Ok(serde_json::to_string(&dummy_cluster()).unwrap()),
958+
(3, &Method::GET) => Ok(serde_json::to_string(&dummy_secret()).unwrap()),
959+
(4, &Method::POST) => Ok(serde_json::to_string(&()).unwrap()),
960+
_ => panic!("unexpected API interaction: {req:?}, counter {ctr}"),
961+
};
962+
count_check!(4, clos, |client| {
963+
assert!(sync_all_machine_luks_key(client).await.is_ok());
964+
});
965+
}
966+
967+
#[tokio::test]
968+
async fn test_sync_all_machine_luks_key_send_fails_gracefully() {
969+
let clos = async |req: Request<_>, ctr| match (ctr, req.method()) {
970+
(0, &Method::GET) => {
971+
let list = kube::api::ObjectList {
972+
items: vec![dummy_machine("m1"), dummy_machine("m2")],
973+
types: Default::default(),
974+
metadata: Default::default(),
975+
};
976+
Ok(serde_json::to_string(&list).unwrap())
977+
}
978+
(_, &Method::GET) => Err(StatusCode::NOT_FOUND),
979+
_ => panic!("unexpected API interaction: {req:?}, counter {ctr}"),
980+
};
981+
count_check!(3, clos, |client| {
982+
assert!(sync_all_machine_luks_key(client).await.is_ok());
983+
});
984+
}
985+
986+
#[tokio::test]
987+
async fn test_update_attestation_keys_empty() {
988+
let clos = async |_, _| {
989+
let list = kube::api::ObjectList {
990+
items: Vec::<Secret>::new(),
991+
types: Default::default(),
992+
metadata: Default::default(),
993+
};
994+
Ok(serde_json::to_string(&list).unwrap())
995+
};
996+
count_check!(1, clos, |client| {
997+
assert!(update_attestation_keys(client).await.is_ok());
998+
});
999+
}
1000+
1001+
#[tokio::test]
1002+
async fn test_update_attestation_keys_register_fails_gracefully() {
1003+
let clos = async |req: Request<_>, ctr| match (ctr, req.method()) {
1004+
(0, &Method::GET) => {
1005+
let list = kube::api::ObjectList {
1006+
items: vec![dummy_ak_secret("ak1"), dummy_ak_secret("ak2")],
1007+
types: Default::default(),
1008+
metadata: Default::default(),
1009+
};
1010+
Ok(serde_json::to_string(&list).unwrap())
1011+
}
1012+
_ => Err(StatusCode::NOT_FOUND),
1013+
};
1014+
count_check!(3, clos, |client| {
1015+
assert!(update_attestation_keys(client).await.is_ok());
1016+
});
1017+
}
1018+
1019+
#[tokio::test]
1020+
async fn test_update_attestation_keys_register_success() {
1021+
let clos = async |req: Request<_>, ctr| match (ctr, req.method()) {
1022+
(0, &Method::GET) => {
1023+
let list = kube::api::ObjectList {
1024+
items: vec![dummy_ak_secret("ak1")],
1025+
types: Default::default(),
1026+
metadata: Default::default(),
1027+
};
1028+
Ok(serde_json::to_string(&list).unwrap())
1029+
}
1030+
(1, &Method::GET) => {
1031+
assert!(req.uri().path().contains(TRUSTEE_AUTH_SECRET));
1032+
Ok(serde_json::to_string(&dummy_trustee_auth()).unwrap())
1033+
}
1034+
(2, &Method::GET) => Ok(serde_json::to_string(&dummy_cluster()).unwrap()),
1035+
(3, &Method::POST) => Ok(serde_json::to_string(&()).unwrap()),
1036+
_ => panic!("unexpected API interaction: {req:?}, counter {ctr}"),
1037+
};
1038+
count_check!(3, clos, |client| {
1039+
assert!(update_attestation_keys(client).await.is_ok());
1040+
});
1041+
}
1042+
1043+
#[tokio::test]
1044+
async fn test_update_attestation_keys_filters_deleting() {
1045+
use k8s_openapi::apimachinery::pkg::apis::meta::v1::Time;
1046+
let clos = async |_, _| {
1047+
let mut deleting = dummy_ak_secret("ak-deleting");
1048+
deleting.metadata.deletion_timestamp = Some(Time(jiff::Timestamp::now()));
1049+
let no_owner = Secret::default();
1050+
let list = kube::api::ObjectList {
1051+
items: vec![deleting, no_owner],
1052+
types: Default::default(),
1053+
metadata: Default::default(),
1054+
};
1055+
Ok(serde_json::to_string(&list).unwrap())
1056+
};
1057+
count_check!(1, clos, |client| {
1058+
assert!(update_attestation_keys(client).await.is_ok());
1059+
});
1060+
}
9221061
}

0 commit comments

Comments
 (0)