- 1
//! `PUT /config/bus` keeps the bus's secrets in the secret store, never in a - 2
//! file (docs/plans/data-architecture-plan.md, M0): the NATS URL goes to the - 3
//! project config, the credentials JWT and nkey seed to the project secret - 4
//! scope, GET never returns them, and DELETE removes both. - 5
- 6
#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)] - 7
- 8
use std::path::Path; - 9
- 10
use vak_core::Core; - 11
- 12
fn files_containing(root: &Path, needle: &str) -> Vec<std::path::PathBuf> { - 13
let mut found = Vec::new(); - 14
let mut stack = vec![root.to_path_buf()]; - 15
while let Some(dir) = stack.pop() { - 16
let Ok(entries) = std::fs::read_dir(&dir) else { - 17
continue; - 18
}; - 19
for entry in entries.flatten() { - 20
let path = entry.path(); - 21
if path.is_dir() { - 22
stack.push(path); - 23
} else if std::fs::read(&path).is_ok_and(|bytes| { - 24
bytes - 25
.windows(needle.len()) - 26
.any(|window| window == needle.as_bytes()) - 27
}) { - 28
found.push(path); - 29
} - 30
} - 31
} - 32
found - 33
} - 34
- 35
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] - 36
async fn bus_credentials_never_written_to_a_file() { - 37
let isolated = vak_config::paths::isolate_home_for_tests(); - 38
let dir = tempfile::tempdir().unwrap(); - 39
let (ws, home) = (dir.path().join("ws"), dir.path().join("home")); - 40
std::fs::create_dir_all(&ws).unwrap(); - 41
let core = Core::new_with_trust(ws.clone(), true).unwrap(); - 42
core.set_sessions_home(home.clone()); - 43
let listener = tokio::net::TcpListener::bind("127.0.0.1:0").await.unwrap(); - 44
let addr = listener.local_addr().unwrap(); - 45
let app = vak_server::router(core.clone()); - 46
tokio::spawn(async move { axum::serve(listener, app).await.unwrap() }); - 47
let client = reqwest::Client::new(); - 48
let base = format!("http://{addr}"); - 49
- 50
let jwt = format!("jwt-secret-{}", uuid::Uuid::now_v7().simple()); - 51
let seed = format!("SUSEED{}", uuid::Uuid::now_v7().simple()); - 52
let response = client - 53
.put(format!("{base}/config/bus")) - 54
.json(&serde_json::json!({ - 55
"nats_url": "nats://127.0.0.1:1", - 56
"nats_credentials_jwt": jwt, - 57
"nats_nkey_seed": seed, - 58
})) - 59
.send() - 60
.await - 61
.unwrap(); - 62
assert_eq!(response.status(), 200, "{}", response.text().await.unwrap()); - 63
- 64
for secret in [&jwt, &seed] { - 65
for root in [&ws, &home, &isolated] { - 66
assert!( - 67
files_containing(root, secret).is_empty(), - 68
"a secret was written to a file under {}", - 69
root.display() - 70
); - 71
} - 72
} - 73
assert_eq!( - 74
core.bus_secret(vak_config::BUS_NATS_JWT_VAR), - 75
Some(jwt.clone()) - 76
); - 77
assert_eq!( - 78
core.bus_secret(vak_config::BUS_NATS_NKEY_SEED_VAR), - 79
Some(seed.clone()) - 80
); - 81
let settings = std::fs::read_to_string(ws.join(".vak/config.toml")).unwrap(); - 82
assert!(settings.contains("nats://127.0.0.1:1"), "{settings}"); - 83
assert!(!ws.join(".vak/env").exists()); - 84
- 85
let shown = client - 86
.get(format!("{base}/config/bus")) - 87
.send() - 88
.await - 89
.unwrap() - 90
.text() - 91
.await - 92
.unwrap(); - 93
assert!(!shown.contains(&jwt) && !shown.contains(&seed), "{shown}"); - 94
- 95
let removed = client - 96
.delete(format!("{base}/config/bus")) - 97
.send() - 98
.await - 99
.unwrap(); - 100
assert_eq!(removed.status(), 200); - 101
assert_eq!(core.bus_secret(vak_config::BUS_NATS_JWT_VAR), None); - 102
assert_eq!(core.bus_secret(vak_config::BUS_NATS_NKEY_SEED_VAR), None); - 103
let settings = std::fs::read_to_string(ws.join(".vak/config.toml")).unwrap(); - 104
assert!(!settings.contains("nats_url"), "{settings}"); - 105
} - 106
Indexing the workspace…
Vakyartha documentation is discovering safe artifacts, anchors, and source references.