Add smooth node enrollment flow
This commit is contained in:
parent
b941037652
commit
27a79768e4
12 changed files with 1662 additions and 22 deletions
|
|
@ -1035,6 +1035,134 @@ fn init_owned_node_records_signed_owner_device_and_node() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn node_enrollment_request_import_and_approval_records_signed_ops() {
|
||||
if Command::new("ssh-keygen").arg("-?").output().is_err() {
|
||||
return;
|
||||
}
|
||||
|
||||
let owner_home = tempfile::tempdir().expect("owner tempdir");
|
||||
let requester_home = tempfile::tempdir().expect("requester tempdir");
|
||||
let owner_paths = geth_config::GethPaths::from_home(owner_home.path());
|
||||
let requester_paths = geth_config::GethPaths::from_home(requester_home.path());
|
||||
let admin_key_path = owner_home.path().join("owner_ed25519");
|
||||
let status = Command::new("ssh-keygen")
|
||||
.arg("-q")
|
||||
.arg("-t")
|
||||
.arg("ed25519")
|
||||
.arg("-N")
|
||||
.arg("")
|
||||
.arg("-f")
|
||||
.arg(&admin_key_path)
|
||||
.status()
|
||||
.expect("generate owner ssh key");
|
||||
assert!(status.success());
|
||||
|
||||
let owner = geth_node::init_owned_node(
|
||||
&owner_paths,
|
||||
geth_node::InitOwnerOptions {
|
||||
admin_key_path: Some(admin_key_path.with_extension("pub")),
|
||||
signing_key_path: Some(admin_key_path.clone()),
|
||||
owner_name: "Eric".to_owned(),
|
||||
node_name: "owner-laptop".to_owned(),
|
||||
capabilities: Vec::new(),
|
||||
},
|
||||
)
|
||||
.expect("init owner");
|
||||
let requester = geth_node::init_node(&requester_paths).expect("init requester");
|
||||
let request_path = requester_home.path().join("enrollment.json");
|
||||
|
||||
let response = geth_node::handle_request(
|
||||
&requester,
|
||||
geth_control::ControlRequest::NodeEnrollRequest {
|
||||
node_name: "workstation".to_owned(),
|
||||
capabilities: vec!["resource:ssh-proxy:local=ssh_proxy.connect".to_owned()],
|
||||
reason: Some("new test machine".to_owned()),
|
||||
out: Some(request_path.clone()),
|
||||
},
|
||||
)
|
||||
.expect("create enrollment request");
|
||||
let request_id = match response {
|
||||
geth_control::ControlResponse::NodeEnrollmentRequested { request, .. } => {
|
||||
assert_eq!(request.requested_node_name, "workstation");
|
||||
assert!(request.provenance.is_some());
|
||||
request.id.to_string()
|
||||
}
|
||||
other => panic!("unexpected response: {other:?}"),
|
||||
};
|
||||
assert!(request_path.exists());
|
||||
|
||||
let imported = geth_node::handle_request(
|
||||
&owner,
|
||||
geth_control::ControlRequest::NodeEnrollImport { path: request_path },
|
||||
)
|
||||
.expect("import request");
|
||||
match imported {
|
||||
geth_control::ControlResponse::NodeEnrollmentImported { request, .. } => {
|
||||
assert_eq!(request.id.as_str(), request_id);
|
||||
assert_eq!(request.status.to_string(), "pending");
|
||||
}
|
||||
other => panic!("unexpected response: {other:?}"),
|
||||
}
|
||||
|
||||
let approved = geth_node::handle_request(
|
||||
&owner,
|
||||
geth_control::ControlRequest::NodeEnrollApprove {
|
||||
request_id: request_id.clone(),
|
||||
signing_key_path: admin_key_path,
|
||||
admin_key_path: None,
|
||||
node_name: None,
|
||||
capabilities: vec!["resource:cas:local=cas.fetch".to_owned()],
|
||||
},
|
||||
)
|
||||
.expect("approve request");
|
||||
match approved {
|
||||
geth_control::ControlResponse::NodeEnrollmentApproved {
|
||||
keychain_ops,
|
||||
keychain_signatures,
|
||||
auth_ops,
|
||||
auth_signatures,
|
||||
..
|
||||
} => {
|
||||
assert!(keychain_ops.len() >= 3);
|
||||
assert_eq!(keychain_signatures.len(), keychain_ops.len());
|
||||
assert_eq!(auth_ops.len(), 2);
|
||||
assert_eq!(auth_signatures.len(), 2);
|
||||
}
|
||||
other => panic!("unexpected response: {other:?}"),
|
||||
}
|
||||
|
||||
match geth_node::handle_request(&owner, geth_control::ControlRequest::NodeList)
|
||||
.expect("node list")
|
||||
{
|
||||
geth_control::ControlResponse::NodeList { nodes, .. } => {
|
||||
assert!(nodes.iter().any(|node| node.name == "workstation"));
|
||||
}
|
||||
other => panic!("unexpected response: {other:?}"),
|
||||
}
|
||||
match geth_node::handle_request(
|
||||
&owner,
|
||||
geth_control::ControlRequest::AuthExplain {
|
||||
subject: requester.node_id.clone(),
|
||||
resource: "resource:ssh-proxy:local".to_owned(),
|
||||
capability: "ssh_proxy.connect".to_owned(),
|
||||
},
|
||||
)
|
||||
.expect("explain enrollment grant")
|
||||
{
|
||||
geth_control::ControlResponse::AuthExplain(explanation) => assert!(explanation.allowed),
|
||||
other => panic!("unexpected response: {other:?}"),
|
||||
}
|
||||
let store = geth_store::Store::open(&owner_paths.metadata_db()).expect("open store");
|
||||
assert_eq!(
|
||||
store
|
||||
.list_auth_signatures()
|
||||
.expect("list auth signatures")
|
||||
.len(),
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn db_add_and_status_register_local_db_metadata() {
|
||||
let home = tempfile::tempdir().expect("tempdir");
|
||||
|
|
|
|||
Loading…
Reference in a new issue