Harden signed node authorization flow

This commit is contained in:
Eric Wendland 2026-05-21 18:15:10 +02:00
commit 1336fa38e8
9 changed files with 382 additions and 55 deletions

View file

@ -160,10 +160,30 @@ pub enum NodeCommand {
capability: String,
#[arg(long)]
grant_id: Option<String>,
#[arg(long)]
signing_key: PathBuf,
#[arg(long)]
admin_key: Option<PathBuf>,
},
RevokeGrant {
resource: String,
grant_id: String,
#[arg(long)]
signing_key: PathBuf,
#[arg(long)]
admin_key: Option<PathBuf>,
},
EndpointAdd {
node: String,
endpoint: String,
#[arg(long)]
signing_key: PathBuf,
},
EndpointRevoke {
node: String,
endpoint: String,
#[arg(long)]
signing_key: PathBuf,
},
}
@ -265,10 +285,18 @@ pub enum AuthCommand {
capability: String,
#[arg(long)]
grant_id: Option<String>,
#[arg(long)]
signing_key: PathBuf,
#[arg(long)]
admin_key: Option<PathBuf>,
},
Revoke {
resource: String,
grant_id: String,
#[arg(long)]
signing_key: PathBuf,
#[arg(long)]
admin_key: Option<PathBuf>,
},
}
@ -871,16 +899,55 @@ fn request_for_command(command: Command) -> Result<ControlRequest> {
resource,
capability,
grant_id,
signing_key,
admin_key,
},
} => ControlRequest::NodeGrant {
node,
resource,
capability,
grant_id,
signing_key_path: Some(signing_key),
admin_key_path: admin_key,
},
Command::Node {
command: NodeCommand::RevokeGrant { resource, grant_id },
} => ControlRequest::NodeRevokeGrant { resource, grant_id },
command:
NodeCommand::RevokeGrant {
resource,
grant_id,
signing_key,
admin_key,
},
} => ControlRequest::NodeRevokeGrant {
resource,
grant_id,
signing_key_path: Some(signing_key),
admin_key_path: admin_key,
},
Command::Node {
command:
NodeCommand::EndpointAdd {
node,
endpoint,
signing_key,
},
} => ControlRequest::NodeEndpointAdd {
node,
endpoint,
signing_key_path: Some(signing_key),
},
Command::Node {
command:
NodeCommand::EndpointRevoke {
node,
endpoint,
signing_key,
},
} => ControlRequest::NodeEndpointRevoke {
node,
endpoint,
signing_key_path: Some(signing_key),
},
Command::Peer { command } => match command {
PeerCommand::Export { out } => ControlRequest::PeerCardExport { out },
PeerCommand::Import { path } => ControlRequest::PeerCardImport { path },
@ -940,16 +1007,31 @@ fn request_for_command(command: Command) -> Result<ControlRequest> {
resource,
capability,
grant_id,
signing_key,
admin_key,
},
} => ControlRequest::AuthGrant {
subject,
resource,
capability,
grant_id,
signing_key_path: Some(signing_key),
admin_key_path: admin_key,
},
Command::Auth {
command: AuthCommand::Revoke { resource, grant_id },
} => ControlRequest::AuthRevoke { resource, grant_id },
command:
AuthCommand::Revoke {
resource,
grant_id,
signing_key,
admin_key,
},
} => ControlRequest::AuthRevoke {
resource,
grant_id,
signing_key_path: Some(signing_key),
admin_key_path: admin_key,
},
Command::Secret { command } => match command {
SecretCommand::Status => ControlRequest::SecretStatus,
SecretCommand::Create { resource } => ControlRequest::SecretCreate { resource },
@ -1905,9 +1987,15 @@ fn print_response(response: ControlResponse, json: bool) -> Result<()> {
println!("reason: {}", explain.reason);
println!("evaluated_ops: {}", explain.evaluated_ops);
}
ControlResponse::AuthOpRecorded { op } => {
ControlResponse::AuthOpRecorded { op, signatures } => {
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
);
}
}
ControlResponse::NodeList { nodes, note } => {
if nodes.is_empty() {