Add owner-rooted node management

This commit is contained in:
Eric Wendland 2026-05-21 11:29:29 +02:00
commit b941037652
9 changed files with 1001 additions and 52 deletions

View file

@ -3,7 +3,7 @@ use geth_cas::{FileConflict, FileRoot, FileRootScan};
use geth_db::{CrSqliteChangeBatch, DbResource};
use geth_discovery::{DiscoveredPeer, PeerCard};
use geth_document::{DocumentResource, DocumentState};
use geth_keychain::{KeychainOp, KeychainOpSignature};
use geth_keychain::{KeychainOp, KeychainOpSignature, NodeRecord};
use geth_kv::{KvEntry, KvResource, KvSyncEntry};
use geth_pipe::{PipeConnection, PipeListener, PipeMessage};
use geth_pubsub::PubsubMessage;
@ -117,11 +117,34 @@ pub enum ControlRequest {
resolution: String,
note: Option<String>,
},
NodeList,
NodeRename {
node: String,
name: String,
signing_key_path: Option<PathBuf>,
},
NodeRevoke {
node: String,
signing_key_path: Option<PathBuf>,
},
NodeGrant {
node: String,
resource: String,
capability: String,
grant_id: Option<String>,
},
NodeRevokeGrant {
resource: String,
grant_id: String,
},
KeychainInit {
admin_key_path: Option<PathBuf>,
signing_key_path: Option<PathBuf>,
},
KeychainStatus,
KeychainSync {
node: String,
},
SecretStatus,
SecretCreate {
resource: String,
@ -498,6 +521,15 @@ pub enum ControlResponse {
ops: Vec<KeychainOp>,
signatures: Vec<KeychainOpSignature>,
},
KeychainSynced {
peer_node_id: String,
peer_agent_id: String,
endpoint_id: String,
ops_imported: usize,
signatures_imported: usize,
invalid_ops_rejected: usize,
note: String,
},
SecretStatus {
secrets: Vec<ResourceMasterSecret>,
},
@ -531,6 +563,19 @@ pub enum ControlResponse {
AuthOpRecorded {
op: AuthOp,
},
NodeList {
nodes: Vec<NodeRecord>,
note: String,
},
NodeKeychainUpdated {
ops: Vec<KeychainOp>,
signatures: Vec<KeychainOpSignature>,
note: String,
},
NodeGrantUpdated {
op: AuthOp,
note: String,
},
SshCertRequested {
request: SshCertRequest,
},
@ -811,6 +856,10 @@ pub enum PeerControlRequest {
peer_card: PeerCard,
nonce: String,
},
KeychainSync {
peer_card: PeerCard,
nonce: String,
},
CasFetch {
peer_card: PeerCard,
hash: BlobHash,
@ -929,6 +978,16 @@ pub enum PeerControlResponse {
nonce: String,
note: String,
},
KeychainSynced {
node_id: String,
agent_id: String,
endpoint_id: String,
remote_endpoint_id: String,
ops: Vec<KeychainOp>,
signatures: Vec<KeychainOpSignature>,
nonce: String,
note: String,
},
CasFetched {
node_id: String,
agent_id: String,
@ -1249,6 +1308,24 @@ mod tests {
request
);
let request = ControlRequest::NodeRename {
node: "laptop".to_owned(),
name: "work-laptop".to_owned(),
signing_key_path: Some(PathBuf::from("admin")),
};
assert_eq!(
decode_request(&encode_request(&request).expect("encode")).expect("decode"),
request
);
let request = ControlRequest::KeychainSync {
node: "work-laptop".to_owned(),
};
assert_eq!(
decode_request(&encode_request(&request).expect("encode")).expect("decode"),
request
);
let request = ControlRequest::CasHas {
hash: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef".into(),
};
@ -1266,6 +1343,34 @@ mod tests {
response
);
let response = ControlResponse::NodeList {
nodes: vec![NodeRecord {
id: geth_types::NodeId::new("node:local"),
device: geth_types::DeviceId::new("device:local"),
name: "work-laptop".to_owned(),
endpoints: Vec::new(),
}],
note: "reduced keychain view".to_owned(),
};
assert_eq!(
decode_response(&encode_response(&response).expect("encode")).expect("decode"),
response
);
let response = ControlResponse::KeychainSynced {
peer_node_id: "node:peer".to_owned(),
peer_agent_id: "agent:peer".to_owned(),
endpoint_id: "endpoint:peer".to_owned(),
ops_imported: 2,
signatures_imported: 2,
invalid_ops_rejected: 1,
note: "trusted admin signatures only".to_owned(),
};
assert_eq!(
decode_response(&encode_response(&response).expect("encode")).expect("decode"),
response
);
let request = ControlRequest::SecretBearerVerify {
secret: "bearer:test".to_owned(),
resource: "resource:cas:local".to_owned(),