Add smooth node enrollment flow
This commit is contained in:
parent
b941037652
commit
27a79768e4
12 changed files with 1662 additions and 22 deletions
|
|
@ -139,6 +139,10 @@ pub enum NodeCommand {
|
|||
Id,
|
||||
Status,
|
||||
List,
|
||||
Enroll {
|
||||
#[command(subcommand)]
|
||||
command: NodeEnrollCommand,
|
||||
},
|
||||
Rename {
|
||||
node: String,
|
||||
name: String,
|
||||
|
|
@ -163,6 +167,48 @@ pub enum NodeCommand {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum NodeEnrollCommand {
|
||||
Request {
|
||||
#[arg(long)]
|
||||
node_name: String,
|
||||
#[arg(long = "capability")]
|
||||
capabilities: Vec<String>,
|
||||
#[arg(long)]
|
||||
reason: Option<String>,
|
||||
#[arg(long)]
|
||||
out: Option<PathBuf>,
|
||||
},
|
||||
Submit {
|
||||
owner_node: String,
|
||||
#[arg(long)]
|
||||
request_id: Option<String>,
|
||||
#[arg(long)]
|
||||
path: Option<PathBuf>,
|
||||
},
|
||||
Import {
|
||||
path: PathBuf,
|
||||
},
|
||||
List {
|
||||
#[arg(long)]
|
||||
status: Option<String>,
|
||||
},
|
||||
Approve {
|
||||
request_id: String,
|
||||
#[arg(long)]
|
||||
signing_key: PathBuf,
|
||||
#[arg(long)]
|
||||
admin_key: Option<PathBuf>,
|
||||
#[arg(long)]
|
||||
node_name: Option<String>,
|
||||
#[arg(long = "capability")]
|
||||
capabilities: Vec<String>,
|
||||
},
|
||||
Sync {
|
||||
owner_node: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
pub enum PeerCommand {
|
||||
Export {
|
||||
|
|
@ -210,6 +256,9 @@ pub enum AuthCommand {
|
|||
resource: String,
|
||||
capability: String,
|
||||
},
|
||||
Sync {
|
||||
node: String,
|
||||
},
|
||||
Grant {
|
||||
subject: String,
|
||||
resource: String,
|
||||
|
|
@ -757,6 +806,46 @@ fn request_for_command(command: Command) -> Result<ControlRequest> {
|
|||
Command::Node {
|
||||
command: NodeCommand::List,
|
||||
} => ControlRequest::NodeList,
|
||||
Command::Node {
|
||||
command: NodeCommand::Enroll { command },
|
||||
} => match command {
|
||||
NodeEnrollCommand::Request {
|
||||
node_name,
|
||||
capabilities,
|
||||
reason,
|
||||
out,
|
||||
} => ControlRequest::NodeEnrollRequest {
|
||||
node_name,
|
||||
capabilities,
|
||||
reason,
|
||||
out,
|
||||
},
|
||||
NodeEnrollCommand::Submit {
|
||||
owner_node,
|
||||
request_id,
|
||||
path,
|
||||
} => ControlRequest::NodeEnrollSubmit {
|
||||
owner_node,
|
||||
request_id,
|
||||
path,
|
||||
},
|
||||
NodeEnrollCommand::Import { path } => ControlRequest::NodeEnrollImport { path },
|
||||
NodeEnrollCommand::List { status } => ControlRequest::NodeEnrollList { status },
|
||||
NodeEnrollCommand::Approve {
|
||||
request_id,
|
||||
signing_key,
|
||||
admin_key,
|
||||
node_name,
|
||||
capabilities,
|
||||
} => ControlRequest::NodeEnrollApprove {
|
||||
request_id,
|
||||
signing_key_path: signing_key,
|
||||
admin_key_path: admin_key,
|
||||
node_name,
|
||||
capabilities,
|
||||
},
|
||||
NodeEnrollCommand::Sync { owner_node } => ControlRequest::NodeEnrollSync { owner_node },
|
||||
},
|
||||
Command::Node {
|
||||
command:
|
||||
NodeCommand::Rename {
|
||||
|
|
@ -829,6 +918,9 @@ fn request_for_command(command: Command) -> Result<ControlRequest> {
|
|||
Command::Keychain {
|
||||
command: KeychainCommand::Sync { node },
|
||||
} => ControlRequest::KeychainSync { node },
|
||||
Command::Auth {
|
||||
command: AuthCommand::Sync { node },
|
||||
} => ControlRequest::AuthSync { node },
|
||||
Command::Auth {
|
||||
command:
|
||||
AuthCommand::Explain {
|
||||
|
|
@ -1687,6 +1779,23 @@ fn print_response(response: ControlResponse, json: bool) -> Result<()> {
|
|||
println!("invalid_ops_rejected: {invalid_ops_rejected}");
|
||||
println!("note: {note}");
|
||||
}
|
||||
ControlResponse::AuthSynced {
|
||||
peer_node_id,
|
||||
peer_agent_id,
|
||||
endpoint_id,
|
||||
ops_imported,
|
||||
signatures_imported,
|
||||
invalid_ops_rejected,
|
||||
note,
|
||||
} => {
|
||||
println!("synced auth from: {peer_node_id}");
|
||||
println!("agent: {peer_agent_id}");
|
||||
println!("endpoint: {endpoint_id}");
|
||||
println!("ops_imported: {ops_imported}");
|
||||
println!("signatures_imported: {signatures_imported}");
|
||||
println!("invalid_ops_rejected: {invalid_ops_rejected}");
|
||||
println!("note: {note}");
|
||||
}
|
||||
ControlResponse::SecretStatus { secrets } => {
|
||||
if secrets.is_empty() {
|
||||
println!("no resource secrets");
|
||||
|
|
@ -1832,9 +1941,96 @@ fn print_response(response: ControlResponse, json: bool) -> Result<()> {
|
|||
}
|
||||
println!("note: {note}");
|
||||
}
|
||||
ControlResponse::NodeGrantUpdated { op, note } => {
|
||||
ControlResponse::NodeGrantUpdated {
|
||||
op,
|
||||
signatures,
|
||||
note,
|
||||
} => {
|
||||
println!("recorded auth op: {}", op.id);
|
||||
println!("resource: {}", op.resource);
|
||||
for signature in signatures {
|
||||
println!(
|
||||
"signed auth op: {} by {} ({})",
|
||||
signature.op_id, signature.signer, signature.namespace
|
||||
);
|
||||
}
|
||||
println!("note: {note}");
|
||||
}
|
||||
ControlResponse::NodeEnrollmentRequested { request, out, note } => {
|
||||
println!("node enrollment request: {}", request.id);
|
||||
println!("node: {}", request.requester_node);
|
||||
println!("requested_name: {}", request.requested_node_name);
|
||||
println!("status: {}", request.status);
|
||||
if let Some(out) = out {
|
||||
println!("written: {}", out.display());
|
||||
}
|
||||
println!("note: {note}");
|
||||
}
|
||||
ControlResponse::NodeEnrollmentSubmitted {
|
||||
request_id,
|
||||
owner_node_id,
|
||||
accepted,
|
||||
note,
|
||||
} => {
|
||||
println!("submitted enrollment request: {request_id}");
|
||||
println!("owner_node: {owner_node_id}");
|
||||
println!("accepted: {accepted}");
|
||||
println!("note: {note}");
|
||||
}
|
||||
ControlResponse::NodeEnrollmentImported { request, note } => {
|
||||
println!("imported enrollment request: {}", request.id);
|
||||
println!("node: {}", request.requester_node);
|
||||
println!("requested_name: {}", request.requested_node_name);
|
||||
println!("status: {}", request.status);
|
||||
println!("note: {note}");
|
||||
}
|
||||
ControlResponse::NodeEnrollmentList { requests, note } => {
|
||||
if requests.is_empty() {
|
||||
println!("no node enrollment requests");
|
||||
} else {
|
||||
for request in requests {
|
||||
println!(
|
||||
"{}\t{}\t{}\t{} capabilities",
|
||||
request.id,
|
||||
request.status,
|
||||
request.requested_node_name,
|
||||
request.requested_capabilities.len()
|
||||
);
|
||||
}
|
||||
}
|
||||
println!("note: {note}");
|
||||
}
|
||||
ControlResponse::NodeEnrollmentApproved {
|
||||
request,
|
||||
keychain_ops,
|
||||
keychain_signatures,
|
||||
auth_ops,
|
||||
auth_signatures,
|
||||
note,
|
||||
} => {
|
||||
println!("approved enrollment request: {}", request.id);
|
||||
println!("node: {}", request.requester_node);
|
||||
println!("keychain_ops: {}", keychain_ops.len());
|
||||
println!("keychain_signatures: {}", keychain_signatures.len());
|
||||
println!("auth_ops: {}", auth_ops.len());
|
||||
println!("auth_signatures: {}", auth_signatures.len());
|
||||
println!("note: {note}");
|
||||
}
|
||||
ControlResponse::NodeEnrollmentSynced {
|
||||
owner_node,
|
||||
keychain_ops_imported,
|
||||
keychain_signatures_imported,
|
||||
auth_ops_imported,
|
||||
auth_signatures_imported,
|
||||
invalid_ops_rejected,
|
||||
note,
|
||||
} => {
|
||||
println!("synced enrollment from: {owner_node}");
|
||||
println!("keychain_ops_imported: {keychain_ops_imported}");
|
||||
println!("keychain_signatures_imported: {keychain_signatures_imported}");
|
||||
println!("auth_ops_imported: {auth_ops_imported}");
|
||||
println!("auth_signatures_imported: {auth_signatures_imported}");
|
||||
println!("invalid_ops_rejected: {invalid_ops_rejected}");
|
||||
println!("note: {note}");
|
||||
}
|
||||
ControlResponse::SshCertRequested { request } => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue