Add smooth node enrollment flow
This commit is contained in:
parent
b941037652
commit
27a79768e4
12 changed files with 1662 additions and 22 deletions
|
|
@ -1,8 +1,11 @@
|
|||
use geth_types::{AgentId, AuthOpId, DeviceId, KeyId, NodeId, UnixMillis, UserId};
|
||||
use geth_types::{
|
||||
AgentId, AuthOpId, Capability, DeviceId, KeyId, NodeId, ResourceId, UnixMillis, UserId,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
pub const KEYCHAIN_SIGNATURE_NAMESPACE: &str = "geth.keychain.v1@geth.local";
|
||||
pub const NODE_ENROLLMENT_REQUEST_NAMESPACE: &str = "geth.node-enrollment-request.v1@geth.local";
|
||||
|
||||
pub type SignedKeychainOp = geth_codec::SignedEnvelope<KeychainOp, KeyId>;
|
||||
|
||||
|
|
@ -38,6 +41,111 @@ pub struct KeychainOpSignature {
|
|||
pub created_at: UnixMillis,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct NodeEnrollmentRequest {
|
||||
pub id: AuthOpId,
|
||||
pub requester_node: NodeId,
|
||||
pub requester_agent: AgentId,
|
||||
pub requester_agent_public_key: String,
|
||||
pub requested_node_name: String,
|
||||
pub requested_capabilities: Vec<NodeEnrollmentCapability>,
|
||||
pub endpoint_id: Option<String>,
|
||||
pub reason: Option<String>,
|
||||
pub status: NodeEnrollmentStatus,
|
||||
pub created_at: UnixMillis,
|
||||
pub provenance: Option<NodeEnrollmentProvenance>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct NodeEnrollmentCapability {
|
||||
pub resource: ResourceId,
|
||||
pub capability: Capability,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct NodeEnrollmentProvenance {
|
||||
pub namespace: String,
|
||||
pub signer_node: NodeId,
|
||||
pub signer_agent: AgentId,
|
||||
pub signer_public_key: String,
|
||||
pub signature_hex: String,
|
||||
pub signed_at: UnixMillis,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum NodeEnrollmentStatus {
|
||||
Pending,
|
||||
Approved,
|
||||
Rejected,
|
||||
}
|
||||
|
||||
impl NodeEnrollmentStatus {
|
||||
#[must_use]
|
||||
pub fn as_str(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Pending => "pending",
|
||||
Self::Approved => "approved",
|
||||
Self::Rejected => "rejected",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for NodeEnrollmentStatus {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::str::FromStr for NodeEnrollmentStatus {
|
||||
type Err = KeychainError;
|
||||
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
match value {
|
||||
"pending" => Ok(Self::Pending),
|
||||
"approved" => Ok(Self::Approved),
|
||||
"rejected" => Ok(Self::Rejected),
|
||||
_ => Err(KeychainError::InvalidEnrollmentStatus(value.to_owned())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct NodeEnrollmentRequestSigningPayload {
|
||||
pub id: AuthOpId,
|
||||
pub requester_node: NodeId,
|
||||
pub requester_agent: AgentId,
|
||||
pub requester_agent_public_key: String,
|
||||
pub requested_node_name: String,
|
||||
pub requested_capabilities: Vec<NodeEnrollmentCapability>,
|
||||
pub endpoint_id: Option<String>,
|
||||
pub reason: Option<String>,
|
||||
pub created_at: UnixMillis,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum KeychainError {
|
||||
#[error("invalid node enrollment status: {0}")]
|
||||
InvalidEnrollmentStatus(String),
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn node_enrollment_request_signing_payload(
|
||||
request: &NodeEnrollmentRequest,
|
||||
) -> NodeEnrollmentRequestSigningPayload {
|
||||
NodeEnrollmentRequestSigningPayload {
|
||||
id: request.id.clone(),
|
||||
requester_node: request.requester_node.clone(),
|
||||
requester_agent: request.requester_agent.clone(),
|
||||
requester_agent_public_key: request.requester_agent_public_key.clone(),
|
||||
requested_node_name: request.requested_node_name.clone(),
|
||||
requested_capabilities: request.requested_capabilities.clone(),
|
||||
endpoint_id: request.endpoint_id.clone(),
|
||||
reason: request.reason.clone(),
|
||||
created_at: request.created_at,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(tag = "kind", rename_all = "kebab-case")]
|
||||
pub enum KeychainOpKind {
|
||||
|
|
|
|||
Loading…
Reference in a new issue