Harden signed node authorization flow
This commit is contained in:
parent
27a79768e4
commit
1336fa38e8
9 changed files with 382 additions and 55 deletions
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -132,10 +132,24 @@ pub enum ControlRequest {
|
|||
resource: String,
|
||||
capability: String,
|
||||
grant_id: Option<String>,
|
||||
signing_key_path: Option<PathBuf>,
|
||||
admin_key_path: Option<PathBuf>,
|
||||
},
|
||||
NodeRevokeGrant {
|
||||
resource: String,
|
||||
grant_id: String,
|
||||
signing_key_path: Option<PathBuf>,
|
||||
admin_key_path: Option<PathBuf>,
|
||||
},
|
||||
NodeEndpointAdd {
|
||||
node: String,
|
||||
endpoint: String,
|
||||
signing_key_path: Option<PathBuf>,
|
||||
},
|
||||
NodeEndpointRevoke {
|
||||
node: String,
|
||||
endpoint: String,
|
||||
signing_key_path: Option<PathBuf>,
|
||||
},
|
||||
NodeEnrollRequest {
|
||||
node_name: String,
|
||||
|
|
@ -219,10 +233,14 @@ pub enum ControlRequest {
|
|||
resource: String,
|
||||
capability: String,
|
||||
grant_id: Option<String>,
|
||||
signing_key_path: Option<PathBuf>,
|
||||
admin_key_path: Option<PathBuf>,
|
||||
},
|
||||
AuthRevoke {
|
||||
resource: String,
|
||||
grant_id: String,
|
||||
signing_key_path: Option<PathBuf>,
|
||||
admin_key_path: Option<PathBuf>,
|
||||
},
|
||||
SshCertRequest {
|
||||
public_key_path: PathBuf,
|
||||
|
|
@ -601,6 +619,7 @@ pub enum ControlResponse {
|
|||
AuthExplain(AuthExplanation),
|
||||
AuthOpRecorded {
|
||||
op: AuthOp,
|
||||
signatures: Vec<AuthOpSignature>,
|
||||
},
|
||||
NodeList {
|
||||
nodes: Vec<NodeRecord>,
|
||||
|
|
|
|||
|
|
@ -5662,16 +5662,35 @@ pub fn handle_request(
|
|||
resource,
|
||||
capability,
|
||||
grant_id,
|
||||
signing_key_path,
|
||||
admin_key_path,
|
||||
} => {
|
||||
let target = resolve_keychain_node(&store, &target)?;
|
||||
let op = record_node_grant(&store, target.as_str(), &resource, &capability, grant_id)?;
|
||||
let op = node_grant_op(target.as_str(), &resource, &capability, grant_id);
|
||||
let signatures = if let Some(signing_key_path) = signing_key_path {
|
||||
store_and_sign_auth_ops(
|
||||
&store,
|
||||
node,
|
||||
std::slice::from_ref(&op),
|
||||
&signing_key_path,
|
||||
admin_key_path.as_deref(),
|
||||
)?
|
||||
} else {
|
||||
store_auth_op(&store, &op)?;
|
||||
Vec::new()
|
||||
};
|
||||
Ok(ControlResponse::NodeGrantUpdated {
|
||||
op,
|
||||
signatures: Vec::new(),
|
||||
note: "recorded resource-scoped node capability grant; auth explain can show the grant path".to_owned(),
|
||||
signatures,
|
||||
note: "recorded signed resource-scoped node capability grant; auth explain can show the grant path".to_owned(),
|
||||
})
|
||||
}
|
||||
ControlRequest::NodeRevokeGrant { resource, grant_id } => {
|
||||
ControlRequest::NodeRevokeGrant {
|
||||
resource,
|
||||
grant_id,
|
||||
signing_key_path,
|
||||
admin_key_path,
|
||||
} => {
|
||||
let created_at = UnixMillis(geth_store::now_ms());
|
||||
let op = AuthOp {
|
||||
id: generated_auth_op_id("grant-revoke", &resource, &grant_id, created_at),
|
||||
|
|
@ -5679,11 +5698,82 @@ pub fn handle_request(
|
|||
created_at,
|
||||
kind: AuthOpKind::GrantRevoke { grant_id },
|
||||
};
|
||||
store_auth_op(&store, &op)?;
|
||||
let signatures = if let Some(signing_key_path) = signing_key_path {
|
||||
store_and_sign_auth_ops(
|
||||
&store,
|
||||
node,
|
||||
std::slice::from_ref(&op),
|
||||
&signing_key_path,
|
||||
admin_key_path.as_deref(),
|
||||
)?
|
||||
} else {
|
||||
store_auth_op(&store, &op)?;
|
||||
Vec::new()
|
||||
};
|
||||
Ok(ControlResponse::NodeGrantUpdated {
|
||||
op,
|
||||
signatures: Vec::new(),
|
||||
note: "recorded capability grant revocation".to_owned(),
|
||||
signatures,
|
||||
note: "recorded signed capability grant revocation".to_owned(),
|
||||
})
|
||||
}
|
||||
ControlRequest::NodeEndpointAdd {
|
||||
node: target,
|
||||
endpoint,
|
||||
signing_key_path,
|
||||
} => {
|
||||
let signing_key_path = signing_key_path
|
||||
.ok_or_else(|| NodeError::SigningKeyRequired("node endpoint add".to_owned()))?;
|
||||
let target = resolve_keychain_node(&store, &target)?;
|
||||
let created_at = UnixMillis(geth_store::now_ms());
|
||||
let op = KeychainOp {
|
||||
id: generated_keychain_op_id("node-endpoint-add", &endpoint, created_at),
|
||||
created_at,
|
||||
kind: KeychainOpKind::NodeEndpointAdd {
|
||||
node: target,
|
||||
endpoint,
|
||||
},
|
||||
};
|
||||
let signatures = store_and_sign_keychain_ops(
|
||||
&store,
|
||||
node,
|
||||
std::slice::from_ref(&op),
|
||||
Some(signing_key_path.as_path()),
|
||||
None,
|
||||
)?;
|
||||
Ok(ControlResponse::NodeKeychainUpdated {
|
||||
ops: vec![op],
|
||||
signatures,
|
||||
note: "recorded signed node endpoint binding".to_owned(),
|
||||
})
|
||||
}
|
||||
ControlRequest::NodeEndpointRevoke {
|
||||
node: target,
|
||||
endpoint,
|
||||
signing_key_path,
|
||||
} => {
|
||||
let signing_key_path = signing_key_path
|
||||
.ok_or_else(|| NodeError::SigningKeyRequired("node endpoint revoke".to_owned()))?;
|
||||
let target = resolve_keychain_node(&store, &target)?;
|
||||
let created_at = UnixMillis(geth_store::now_ms());
|
||||
let op = KeychainOp {
|
||||
id: generated_keychain_op_id("node-endpoint-revoke", &endpoint, created_at),
|
||||
created_at,
|
||||
kind: KeychainOpKind::NodeEndpointRevoke {
|
||||
node: target,
|
||||
endpoint,
|
||||
},
|
||||
};
|
||||
let signatures = store_and_sign_keychain_ops(
|
||||
&store,
|
||||
node,
|
||||
std::slice::from_ref(&op),
|
||||
Some(signing_key_path.as_path()),
|
||||
None,
|
||||
)?;
|
||||
Ok(ControlResponse::NodeKeychainUpdated {
|
||||
ops: vec![op],
|
||||
signatures,
|
||||
note: "recorded signed node endpoint revocation".to_owned(),
|
||||
})
|
||||
}
|
||||
ControlRequest::NodeEnrollRequest {
|
||||
|
|
@ -5985,6 +6075,8 @@ pub fn handle_request(
|
|||
resource,
|
||||
capability,
|
||||
grant_id,
|
||||
signing_key_path,
|
||||
admin_key_path,
|
||||
} => {
|
||||
let created_at = UnixMillis(geth_store::now_ms());
|
||||
let grant_id =
|
||||
|
|
@ -5999,10 +6091,26 @@ pub fn handle_request(
|
|||
capabilities: vec![Capability::new(capability)],
|
||||
},
|
||||
};
|
||||
store_auth_op(&store, &op)?;
|
||||
Ok(ControlResponse::AuthOpRecorded { op })
|
||||
let signatures = if let Some(signing_key_path) = signing_key_path {
|
||||
store_and_sign_auth_ops(
|
||||
&store,
|
||||
node,
|
||||
std::slice::from_ref(&op),
|
||||
&signing_key_path,
|
||||
admin_key_path.as_deref(),
|
||||
)?
|
||||
} else {
|
||||
store_auth_op(&store, &op)?;
|
||||
Vec::new()
|
||||
};
|
||||
Ok(ControlResponse::AuthOpRecorded { op, signatures })
|
||||
}
|
||||
ControlRequest::AuthRevoke { resource, grant_id } => {
|
||||
ControlRequest::AuthRevoke {
|
||||
resource,
|
||||
grant_id,
|
||||
signing_key_path,
|
||||
admin_key_path,
|
||||
} => {
|
||||
let created_at = UnixMillis(geth_store::now_ms());
|
||||
let op = AuthOp {
|
||||
id: generated_auth_op_id("grant-revoke", &resource, &grant_id, created_at),
|
||||
|
|
@ -6010,8 +6118,19 @@ pub fn handle_request(
|
|||
created_at,
|
||||
kind: AuthOpKind::GrantRevoke { grant_id },
|
||||
};
|
||||
store_auth_op(&store, &op)?;
|
||||
Ok(ControlResponse::AuthOpRecorded { op })
|
||||
let signatures = if let Some(signing_key_path) = signing_key_path {
|
||||
store_and_sign_auth_ops(
|
||||
&store,
|
||||
node,
|
||||
std::slice::from_ref(&op),
|
||||
&signing_key_path,
|
||||
admin_key_path.as_deref(),
|
||||
)?
|
||||
} else {
|
||||
store_auth_op(&store, &op)?;
|
||||
Vec::new()
|
||||
};
|
||||
Ok(ControlResponse::AuthOpRecorded { op, signatures })
|
||||
}
|
||||
ControlRequest::SshCertRequest {
|
||||
public_key_path,
|
||||
|
|
@ -7733,9 +7852,20 @@ fn record_node_grant(
|
|||
capability: &str,
|
||||
grant_id: Option<String>,
|
||||
) -> Result<AuthOp, NodeError> {
|
||||
let op = node_grant_op(node_id, resource, capability, grant_id);
|
||||
store_auth_op(store, &op)?;
|
||||
Ok(op)
|
||||
}
|
||||
|
||||
fn node_grant_op(
|
||||
node_id: &str,
|
||||
resource: &str,
|
||||
capability: &str,
|
||||
grant_id: Option<String>,
|
||||
) -> AuthOp {
|
||||
let created_at = UnixMillis(geth_store::now_ms());
|
||||
let grant_id = grant_id.unwrap_or_else(|| generated_grant_id(node_id, resource, capability));
|
||||
let op = AuthOp {
|
||||
AuthOp {
|
||||
id: generated_auth_op_id("grant-create", resource, &grant_id, created_at),
|
||||
resource: ResourceId::new(resource.to_owned()),
|
||||
created_at,
|
||||
|
|
@ -7744,9 +7874,7 @@ fn record_node_grant(
|
|||
principal: PrincipalId::new(node_id.to_owned()),
|
||||
capabilities: vec![Capability::new(capability.to_owned())],
|
||||
},
|
||||
};
|
||||
store_auth_op(store, &op)?;
|
||||
Ok(op)
|
||||
}
|
||||
}
|
||||
|
||||
fn stable_slug(value: &str) -> String {
|
||||
|
|
@ -9447,6 +9575,8 @@ mod tests {
|
|||
resource: "resource:cas:local".to_owned(),
|
||||
capability: "cas.fetch".to_owned(),
|
||||
grant_id: Some("grant:left-cas-fetch".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left peer");
|
||||
|
|
@ -9457,6 +9587,8 @@ mod tests {
|
|||
resource: "resource:cas-tree:shared".to_owned(),
|
||||
capability: "cas.fetch".to_owned(),
|
||||
grant_id: Some("grant:left-cas-tree-fetch".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left file root fetch");
|
||||
|
|
@ -9467,6 +9599,8 @@ mod tests {
|
|||
resource: "resource:kv:prefs".to_owned(),
|
||||
capability: "kv.read".to_owned(),
|
||||
grant_id: Some("grant:left-kv-read".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left kv read");
|
||||
|
|
@ -9477,6 +9611,8 @@ mod tests {
|
|||
resource: "resource:pubsub:presence/test".to_owned(),
|
||||
capability: "pubsub.publish".to_owned(),
|
||||
grant_id: Some("grant:left-pubsub-publish".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left pubsub publish");
|
||||
|
|
@ -9487,6 +9623,8 @@ mod tests {
|
|||
resource: "resource:pubsub:presence/test".to_owned(),
|
||||
capability: "pubsub.subscribe".to_owned(),
|
||||
grant_id: Some("grant:left-pubsub-subscribe".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left pubsub subscribe");
|
||||
|
|
@ -9497,6 +9635,8 @@ mod tests {
|
|||
resource: "resource:pipe:inbox".to_owned(),
|
||||
capability: "pipe.connect".to_owned(),
|
||||
grant_id: Some("grant:left-pipe-connect".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left pipe connect");
|
||||
|
|
@ -9507,6 +9647,8 @@ mod tests {
|
|||
resource: "resource:pipe:remote-inbox".to_owned(),
|
||||
capability: "pipe.listen".to_owned(),
|
||||
grant_id: Some("grant:left-pipe-listen".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left pipe listen");
|
||||
|
|
@ -9517,6 +9659,8 @@ mod tests {
|
|||
resource: "resource:ssh-proxy:local".to_owned(),
|
||||
capability: "ssh_proxy.connect".to_owned(),
|
||||
grant_id: Some("grant:left-ssh-proxy-connect".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left ssh proxy connect");
|
||||
|
|
@ -9527,6 +9671,8 @@ mod tests {
|
|||
resource: "resource:ssh-proxy:local".to_owned(),
|
||||
capability: "ssh_proxy.admin_shell".to_owned(),
|
||||
grant_id: Some("grant:left-ssh-admin-shell".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left ssh admin shell");
|
||||
|
|
@ -9537,6 +9683,8 @@ mod tests {
|
|||
resource: "resource:document:notes".to_owned(),
|
||||
capability: "document.read".to_owned(),
|
||||
grant_id: Some("grant:left-document-read".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left document read");
|
||||
|
|
@ -9547,6 +9695,8 @@ mod tests {
|
|||
resource: "resource:db:notes".to_owned(),
|
||||
capability: "db.sync".to_owned(),
|
||||
grant_id: Some("grant:left-db-sync".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left db sync");
|
||||
|
|
@ -9562,6 +9712,8 @@ mod tests {
|
|||
resource: format!("resource:pipe-tcp:{tcp_target}"),
|
||||
capability: "pipe.forward".to_owned(),
|
||||
grant_id: Some("grant:left-pipe-tcp-forward".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left pipe tcp forward");
|
||||
|
|
@ -9638,6 +9790,8 @@ mod tests {
|
|||
resource: format!("resource:pipe-unix:{unix_target_display}"),
|
||||
capability: "pipe.forward".to_owned(),
|
||||
grant_id: Some("grant:left-pipe-unix-forward".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left pipe unix forward");
|
||||
|
|
@ -10201,6 +10355,8 @@ mod tests {
|
|||
resource: "resource:ssh:certs".to_owned(),
|
||||
capability: "ssh_cert.sync".to_owned(),
|
||||
grant_id: Some("grant:left-ssh-cert-sync".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left ssh cert sync");
|
||||
|
|
@ -10211,6 +10367,8 @@ mod tests {
|
|||
resource: "resource:ssh:revocations".to_owned(),
|
||||
capability: "ssh_revocation.sync".to_owned(),
|
||||
grant_id: Some("grant:left-ssh-revocation-sync".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant left ssh revocation sync");
|
||||
|
|
|
|||
|
|
@ -786,12 +786,15 @@ fn auth_grant_revoke_and_explain_use_local_auth_log() {
|
|||
resource: "resource:cas:local".to_owned(),
|
||||
capability: "cas.fetch".to_owned(),
|
||||
grant_id: Some("grant:test-fetch".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant capability");
|
||||
match response {
|
||||
geth_control::ControlResponse::AuthOpRecorded { op } => {
|
||||
geth_control::ControlResponse::AuthOpRecorded { op, signatures } => {
|
||||
assert_eq!(op.resource.to_string(), "resource:cas:local");
|
||||
assert!(signatures.is_empty());
|
||||
}
|
||||
other => panic!("unexpected response: {other:?}"),
|
||||
}
|
||||
|
|
@ -819,6 +822,8 @@ fn auth_grant_revoke_and_explain_use_local_auth_log() {
|
|||
geth_control::ControlRequest::AuthRevoke {
|
||||
resource: "resource:cas:local".to_owned(),
|
||||
grant_id: "grant:test-fetch".to_owned(),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("revoke grant");
|
||||
|
|
@ -1006,7 +1011,7 @@ fn init_owned_node_records_signed_owner_device_and_node() {
|
|||
geth_control::ControlRequest::NodeRename {
|
||||
node: "laptop".to_owned(),
|
||||
name: "work-laptop".to_owned(),
|
||||
signing_key_path: Some(admin_key_path),
|
||||
signing_key_path: Some(admin_key_path.clone()),
|
||||
},
|
||||
)
|
||||
.expect("rename node");
|
||||
|
|
@ -1017,6 +1022,41 @@ fn init_owned_node_records_signed_owner_device_and_node() {
|
|||
other => panic!("unexpected response: {other:?}"),
|
||||
}
|
||||
|
||||
let endpoint_added = geth_node::handle_request(
|
||||
&node,
|
||||
geth_control::ControlRequest::NodeEndpointAdd {
|
||||
node: "work-laptop".to_owned(),
|
||||
endpoint: "endpoint:test-rotated".to_owned(),
|
||||
signing_key_path: Some(admin_key_path.clone()),
|
||||
},
|
||||
)
|
||||
.expect("add endpoint");
|
||||
match endpoint_added {
|
||||
geth_control::ControlResponse::NodeKeychainUpdated { signatures, .. } => {
|
||||
assert_eq!(signatures.len(), 1);
|
||||
}
|
||||
other => panic!("unexpected response: {other:?}"),
|
||||
}
|
||||
|
||||
let grant = geth_node::handle_request(
|
||||
&node,
|
||||
geth_control::ControlRequest::NodeGrant {
|
||||
node: "work-laptop".to_owned(),
|
||||
resource: "resource:cas:local".to_owned(),
|
||||
capability: "cas.fetch".to_owned(),
|
||||
grant_id: Some("grant:work-laptop-cas-fetch".to_owned()),
|
||||
signing_key_path: Some(admin_key_path.clone()),
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("signed node grant");
|
||||
match grant {
|
||||
geth_control::ControlResponse::NodeGrantUpdated { signatures, .. } => {
|
||||
assert_eq!(signatures.len(), 1);
|
||||
}
|
||||
other => panic!("unexpected response: {other:?}"),
|
||||
}
|
||||
|
||||
let explained = geth_node::handle_request(
|
||||
&node,
|
||||
geth_control::ControlRequest::AuthExplain {
|
||||
|
|
@ -1388,6 +1428,8 @@ fn kv_create_set_get_use_local_store() {
|
|||
resource: "resource:kv:prefs".to_owned(),
|
||||
capability: "kv.write_prefix:apps/foo/".to_owned(),
|
||||
grant_id: None,
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant prefix write");
|
||||
|
|
@ -2134,6 +2176,8 @@ fn ssh_cert_and_revocation_commands_check_subject_capabilities() {
|
|||
resource: "resource:ssh:certs".to_owned(),
|
||||
capability: "ssh_cert.request".to_owned(),
|
||||
grant_id: Some("grant:ssh-cert-request".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant cert request");
|
||||
|
|
@ -2171,6 +2215,8 @@ fn ssh_cert_and_revocation_commands_check_subject_capabilities() {
|
|||
resource: "resource:ssh:revocations".to_owned(),
|
||||
capability: "ssh_revocation.publish".to_owned(),
|
||||
grant_id: Some("grant:ssh-revocation-publish".to_owned()),
|
||||
signing_key_path: None,
|
||||
admin_key_path: None,
|
||||
},
|
||||
)
|
||||
.expect("grant revocation publish");
|
||||
|
|
|
|||
Loading…
Reference in a new issue