Test owner approved enrollment sync flow
This commit is contained in:
parent
74cee49a1a
commit
94ad64d0db
3 changed files with 288 additions and 6 deletions
|
|
@ -36,6 +36,24 @@ fn spawn_daemon(home: &std::path::Path) -> Child {
|
|||
.expect("spawn daemon")
|
||||
}
|
||||
|
||||
fn ssh_keygen_available() -> bool {
|
||||
Command::new("ssh-keygen").arg("-?").output().is_ok()
|
||||
}
|
||||
|
||||
fn generate_ssh_key(path: &std::path::Path) {
|
||||
let status = Command::new("ssh-keygen")
|
||||
.arg("-q")
|
||||
.arg("-t")
|
||||
.arg("ed25519")
|
||||
.arg("-N")
|
||||
.arg("")
|
||||
.arg("-f")
|
||||
.arg(path)
|
||||
.status()
|
||||
.expect("generate ssh key");
|
||||
assert!(status.success());
|
||||
}
|
||||
|
||||
fn wait_for_socket(path: &std::path::Path) {
|
||||
let started = Instant::now();
|
||||
while started.elapsed() < Duration::from_secs(5) {
|
||||
|
|
@ -197,6 +215,262 @@ fn peer_ping_uses_daemon_owned_iroh_endpoint() {
|
|||
assert!(stdout.contains("candidate status does not grant resource capabilities"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sync_now_completes_owner_approved_node_enrollment_flow() {
|
||||
if !ssh_keygen_available() {
|
||||
return;
|
||||
}
|
||||
|
||||
let owner_home = tempfile::tempdir().expect("owner tempdir");
|
||||
let requester_home = tempfile::tempdir().expect("requester tempdir");
|
||||
if !unix_sockets_available(owner_home.path()) || !unix_sockets_available(requester_home.path())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let owner_key = owner_home.path().join("owner_ed25519");
|
||||
generate_ssh_key(&owner_key);
|
||||
let owner_pub = owner_key.with_extension("pub");
|
||||
let owner_pub_arg = owner_pub.to_str().expect("owner pub path");
|
||||
let owner_key_arg = owner_key.to_str().expect("owner key path");
|
||||
|
||||
let owner_init = run_geth(
|
||||
owner_home.path(),
|
||||
&[
|
||||
"init",
|
||||
"--admin-key",
|
||||
owner_pub_arg,
|
||||
"--signing-key",
|
||||
owner_key_arg,
|
||||
"--owner",
|
||||
"Eric",
|
||||
"--node-name",
|
||||
"owner-laptop",
|
||||
],
|
||||
);
|
||||
assert!(
|
||||
owner_init.status.success(),
|
||||
"owner init stderr: {}",
|
||||
String::from_utf8_lossy(&owner_init.stderr)
|
||||
);
|
||||
let requester_init = run_geth(requester_home.path(), &["init"]);
|
||||
assert!(
|
||||
requester_init.status.success(),
|
||||
"requester init stderr: {}",
|
||||
String::from_utf8_lossy(&requester_init.stderr)
|
||||
);
|
||||
for home in [owner_home.path(), requester_home.path()] {
|
||||
std::fs::write(
|
||||
home.join("config.toml"),
|
||||
"[iroh]\nrelay_mode = \"disabled\"\nlocal_discovery = false\n",
|
||||
)
|
||||
.expect("write config");
|
||||
}
|
||||
|
||||
let mut owner_daemon = spawn_daemon(owner_home.path());
|
||||
let mut requester_daemon = spawn_daemon(requester_home.path());
|
||||
wait_for_socket(&owner_home.path().join("run/geth.sock"));
|
||||
wait_for_socket(&requester_home.path().join("run/geth.sock"));
|
||||
|
||||
let requester_trust = run_geth(
|
||||
requester_home.path(),
|
||||
&["keychain", "init", "--admin-key", owner_pub_arg],
|
||||
);
|
||||
assert!(
|
||||
requester_trust.status.success(),
|
||||
"requester trust stderr: {}",
|
||||
String::from_utf8_lossy(&requester_trust.stderr)
|
||||
);
|
||||
|
||||
let owner_card_path = owner_home.path().join("owner-peer-card.json");
|
||||
let requester_card_path = requester_home.path().join("requester-peer-card.json");
|
||||
let owner_export = run_geth(
|
||||
owner_home.path(),
|
||||
&[
|
||||
"peer",
|
||||
"export",
|
||||
"--out",
|
||||
owner_card_path.to_str().expect("owner card path"),
|
||||
],
|
||||
);
|
||||
let requester_export = run_geth(
|
||||
requester_home.path(),
|
||||
&[
|
||||
"peer",
|
||||
"export",
|
||||
"--out",
|
||||
requester_card_path.to_str().expect("requester card path"),
|
||||
],
|
||||
);
|
||||
assert!(
|
||||
owner_export.status.success(),
|
||||
"owner export stderr: {}",
|
||||
String::from_utf8_lossy(&owner_export.stderr)
|
||||
);
|
||||
assert!(
|
||||
requester_export.status.success(),
|
||||
"requester export stderr: {}",
|
||||
String::from_utf8_lossy(&requester_export.stderr)
|
||||
);
|
||||
let owner_card_json = std::fs::read_to_string(&owner_card_path).expect("read owner card");
|
||||
let owner_card: geth_discovery::PeerCard =
|
||||
serde_json::from_str(&owner_card_json).expect("decode owner card");
|
||||
let requester_card_json =
|
||||
std::fs::read_to_string(&requester_card_path).expect("read requester card");
|
||||
let requester_card: geth_discovery::PeerCard =
|
||||
serde_json::from_str(&requester_card_json).expect("decode requester card");
|
||||
|
||||
let import_owner = run_geth(
|
||||
requester_home.path(),
|
||||
&[
|
||||
"peer",
|
||||
"import",
|
||||
owner_card_path.to_str().expect("owner card path"),
|
||||
],
|
||||
);
|
||||
let import_requester = run_geth(
|
||||
owner_home.path(),
|
||||
&[
|
||||
"peer",
|
||||
"import",
|
||||
requester_card_path.to_str().expect("requester card path"),
|
||||
],
|
||||
);
|
||||
assert!(
|
||||
import_owner.status.success(),
|
||||
"requester import owner stderr: {}",
|
||||
String::from_utf8_lossy(&import_owner.stderr)
|
||||
);
|
||||
assert!(
|
||||
import_requester.status.success(),
|
||||
"owner import requester stderr: {}",
|
||||
String::from_utf8_lossy(&import_requester.stderr)
|
||||
);
|
||||
|
||||
let enroll_request = run_geth(
|
||||
requester_home.path(),
|
||||
&[
|
||||
"node",
|
||||
"enroll",
|
||||
"request",
|
||||
"--node-name",
|
||||
"workstation",
|
||||
"--capability",
|
||||
"resource:ssh-proxy:local=ssh_proxy.connect",
|
||||
],
|
||||
);
|
||||
assert!(
|
||||
enroll_request.status.success(),
|
||||
"enroll request stderr: {}",
|
||||
String::from_utf8_lossy(&enroll_request.stderr)
|
||||
);
|
||||
let enroll_submit = run_geth(
|
||||
requester_home.path(),
|
||||
&["node", "enroll", "submit", owner_card.node_id.as_str()],
|
||||
);
|
||||
assert!(
|
||||
enroll_submit.status.success(),
|
||||
"enroll submit stderr: {}",
|
||||
String::from_utf8_lossy(&enroll_submit.stderr)
|
||||
);
|
||||
assert!(String::from_utf8_lossy(&enroll_submit.stdout).contains("accepted: true"));
|
||||
|
||||
let enroll_list = run_geth(owner_home.path(), &["node", "enroll", "list"]);
|
||||
assert!(
|
||||
enroll_list.status.success(),
|
||||
"enroll list stderr: {}",
|
||||
String::from_utf8_lossy(&enroll_list.stderr)
|
||||
);
|
||||
let enroll_list_stdout = String::from_utf8_lossy(&enroll_list.stdout);
|
||||
let request_id = enroll_list_stdout
|
||||
.lines()
|
||||
.find_map(|line| {
|
||||
let mut fields = line.split('\t');
|
||||
let id = fields.next()?;
|
||||
if id.starts_with("node-enrollment:") {
|
||||
Some(id.to_owned())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.expect("request id in enrollment list");
|
||||
|
||||
let approve = run_geth(
|
||||
owner_home.path(),
|
||||
&[
|
||||
"node",
|
||||
"enroll",
|
||||
"approve",
|
||||
&request_id,
|
||||
"--signing-key",
|
||||
owner_key_arg,
|
||||
"--capability",
|
||||
"resource:cas:local=cas.fetch",
|
||||
],
|
||||
);
|
||||
assert!(
|
||||
approve.status.success(),
|
||||
"approve stderr: {}",
|
||||
String::from_utf8_lossy(&approve.stderr)
|
||||
);
|
||||
|
||||
let sync = run_geth(
|
||||
requester_home.path(),
|
||||
&["sync", "now", owner_card.node_id.as_str()],
|
||||
);
|
||||
assert!(
|
||||
sync.status.success(),
|
||||
"sync now stderr: {}",
|
||||
String::from_utf8_lossy(&sync.stderr)
|
||||
);
|
||||
let sync_stdout = String::from_utf8_lossy(&sync.stdout);
|
||||
assert!(sync_stdout.contains("keychain\tok"));
|
||||
assert!(sync_stdout.contains("auth\tok"));
|
||||
|
||||
let requester_nodes = run_geth(requester_home.path(), &["node", "list"]);
|
||||
assert!(
|
||||
requester_nodes.status.success(),
|
||||
"requester node list stderr: {}",
|
||||
String::from_utf8_lossy(&requester_nodes.stderr)
|
||||
);
|
||||
let requester_nodes_stdout = String::from_utf8_lossy(&requester_nodes.stdout);
|
||||
assert!(requester_nodes_stdout.contains("owner-laptop"));
|
||||
assert!(requester_nodes_stdout.contains("workstation"));
|
||||
|
||||
let explain = run_geth(
|
||||
requester_home.path(),
|
||||
&[
|
||||
"auth",
|
||||
"explain",
|
||||
requester_card.node_id.as_str(),
|
||||
"resource:ssh-proxy:local",
|
||||
"ssh_proxy.connect",
|
||||
],
|
||||
);
|
||||
assert!(
|
||||
explain.status.success(),
|
||||
"auth explain stderr: {}",
|
||||
String::from_utf8_lossy(&explain.stderr)
|
||||
);
|
||||
assert!(String::from_utf8_lossy(&explain.stdout).contains("allowed: true"));
|
||||
|
||||
let sync_status = run_geth(requester_home.path(), &["sync", "status"]);
|
||||
let _ = owner_daemon.kill();
|
||||
let _ = requester_daemon.kill();
|
||||
let _ = owner_daemon.wait();
|
||||
let _ = requester_daemon.wait();
|
||||
|
||||
assert!(
|
||||
sync_status.status.success(),
|
||||
"sync status stderr: {}",
|
||||
String::from_utf8_lossy(&sync_status.stderr)
|
||||
);
|
||||
let sync_status_stdout = String::from_utf8_lossy(&sync_status.stdout);
|
||||
assert!(sync_status_stdout.contains("peer:"));
|
||||
assert!(sync_status_stdout.contains("keychain"));
|
||||
assert!(sync_status_stdout.contains("auth"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn peer_card_export_import_and_list_are_candidate_only() {
|
||||
let source_home = tempfile::tempdir().expect("source tempdir");
|
||||
|
|
|
|||
Loading…
Reference in a new issue