Skip to content

Commit 4bc5e24

Browse files
committed
fix(iotwireless): project partner-account fields at top level for ListPartnerAccounts
AssociateAwsAccountWithPartnerAccount stored the Sidewalk info nested, but the generic ListPartnerAccounts projection reads AmazonId/Fingerprint/Arn from the record's top level, so the account never appeared in the list. Store the projected members at top level (plus a deterministic key fingerprint, never the private key) and keep the nested Sidewalk object for GetPartnerAccount.
1 parent 51f46b6 commit 4bc5e24

1 file changed

Lines changed: 37 additions & 1 deletion

File tree

  • crates/fakecloud-iotwireless/src/service

crates/fakecloud-iotwireless/src/service/special.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,24 @@ fn get_wireless_gateway_certificate(
863863
(ok_json(json!({ "IotCertificateId": cert })), false)
864864
}
865865

866+
/// A deterministic 64-character hex digest of an input, standing in for the
867+
/// SHA-256 fingerprint AWS reports for a Sidewalk app-server private key. Built
868+
/// from eight salted FNV-1a folds so the same key always maps to the same
869+
/// digest without pulling in a crypto dependency.
870+
fn fingerprint_hex(input: &str) -> String {
871+
let mut out = String::with_capacity(64);
872+
for salt in 0u8..8 {
873+
let mut hash: u64 = 0xcbf2_9ce4_8422_2325;
874+
hash ^= salt as u64;
875+
for b in input.bytes() {
876+
hash ^= b as u64;
877+
hash = hash.wrapping_mul(0x0000_0100_0000_01b3);
878+
}
879+
out.push_str(&format!("{hash:016x}"));
880+
}
881+
out
882+
}
883+
866884
/// Persist a Sidewalk partner-account association keyed by its AmazonId so
867885
/// GetPartnerAccount / ListPartnerAccounts (generic reads) reflect it.
868886
fn associate_partner_account(
@@ -876,8 +894,26 @@ fn associate_partner_account(
876894
.and_then(Value::as_str)
877895
.unwrap_or("")
878896
.to_string();
897+
// AWS returns a fingerprint of the app-server private key, never the key
898+
// itself. Derive a deterministic 64-hex digest so Get/List round-trip.
899+
let private_key = sidewalk
900+
.get("AppServerPrivateKey")
901+
.and_then(Value::as_str)
902+
.unwrap_or("");
903+
let fingerprint = fingerprint_hex(private_key);
904+
// The SidewalkAccountInfoWithFingerprint the reads project carries the
905+
// AmazonId + Fingerprint (never the private key).
906+
let sidewalk_with_fp = json!({
907+
"AmazonId": amazon_id,
908+
"Fingerprint": fingerprint,
909+
});
910+
// Store the projected list-element members (AmazonId/Fingerprint/Arn) at the
911+
// top level so the generic ListPartnerAccounts projection finds them, and
912+
// keep the nested Sidewalk object for GetPartnerAccount.
879913
let record = json!({
880-
"Sidewalk": sidewalk,
914+
"AmazonId": amazon_id,
915+
"Fingerprint": fingerprint,
916+
"Sidewalk": sidewalk_with_fp,
881917
"PartnerAccountId": amazon_id,
882918
"PartnerType": "Sidewalk",
883919
});

0 commit comments

Comments
 (0)