2023-03-29 15:18:33 +00:00
|
|
|
//! Models for interacting with the Defined Networking API.
|
|
|
|
|
|
|
|
use base64_serde::base64_serde_type;
|
|
|
|
use serde::{Serialize, Deserialize};
|
|
|
|
|
|
|
|
/// The version 1 `DNClient` API endpoint
|
2023-03-29 18:31:07 +00:00
|
|
|
pub const ENDPOINT_V1: &str = "/v1/dnclient";
|
2023-03-29 15:18:33 +00:00
|
|
|
|
2023-03-29 21:42:16 +00:00
|
|
|
/// The CheckForUpdate message type
|
|
|
|
pub const CHECK_FOR_UPDATE: &str = "CheckForUpdate";
|
|
|
|
/// The DoUpdate message type
|
|
|
|
pub const DO_UPDATE: &str = "DoUpdate";
|
|
|
|
|
2023-03-29 15:18:33 +00:00
|
|
|
base64_serde_type!(Base64Standard, base64::engine::general_purpose::STANDARD);
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
/// `RequestV1` is the version 1 `DNClient` request message.
|
|
|
|
pub struct RequestV1 {
|
|
|
|
/// Version is always 1
|
|
|
|
pub version: i32,
|
|
|
|
#[serde(rename = "hostID")]
|
|
|
|
/// The Host ID of this dnclient instance
|
|
|
|
pub host_id: String,
|
|
|
|
/// The counter last returned by the server
|
|
|
|
pub counter: u32,
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// A base64-encoded message
|
|
|
|
pub message: Vec<u8>,
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// An ed25519 signature over the `message`, which can be verified with the host's previously enrolled ed25519 public key
|
|
|
|
pub signature: Vec<u8>
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
/// `RequestWrapper` wraps a `DNClient` request message. It consists of a
|
|
|
|
/// type and value, with the type string indicating how to interpret the value blob.
|
|
|
|
pub struct RequestWrapper {
|
|
|
|
#[serde(rename = "type")]
|
|
|
|
/// The type of the message. Used to determine how `value` is encoded
|
|
|
|
pub message_type: String,
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// A base64-encoded arbitrary message, the type of which is stated in `message_type`
|
|
|
|
pub value: Vec<u8>,
|
|
|
|
/// The timestamp of when this message was sent. Follows the format `%Y-%m-%dT%H:%M:%S.%f%:z`, or:
|
|
|
|
/// <4-digit year>-<two-digit-month>-<two-digit-day>T<two-digit-hour, 24-hour>:<two-digit-minute>:<two-digit-second>.<nanoseconds, zero-padded><offset with semicolon>
|
|
|
|
/// For example:
|
|
|
|
/// `2023-03-29T09:56:42.380006369-04:00`
|
|
|
|
/// would represent `29 March 03, 2023, 09:56:42.380006369 UTC-4`
|
|
|
|
pub timestamp: String
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
/// `SignedResponseWrapper` contains a response message and a signature to validate inside `data`.
|
|
|
|
pub struct SignedResponseWrapper {
|
|
|
|
/// The response data contained in this message
|
|
|
|
pub data: SignedResponse
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
/// `SignedResponse` contains a response message and a signature to validate.
|
|
|
|
pub struct SignedResponse {
|
|
|
|
/// The API version - always 1
|
|
|
|
pub version: i32,
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// The Base64-encoded message signed inside this message
|
|
|
|
pub message: Vec<u8>,
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// The ed25519 signature over the `message`
|
|
|
|
pub signature: Vec<u8>
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
/// `CheckForUpdateResponseWrapper` contains a response to `CheckForUpdate` inside "data."
|
|
|
|
pub struct CheckForUpdateResponseWrapper {
|
|
|
|
/// The response data contained in this message
|
|
|
|
pub data: CheckForUpdateResponse
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
/// `CheckForUpdateResponse` is the response generated for a `CheckForUpdate` request.
|
|
|
|
pub struct CheckForUpdateResponse {
|
|
|
|
#[serde(rename = "updateAvailable")]
|
|
|
|
/// Set to true if a config update is available
|
|
|
|
pub update_available: bool
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
/// `DoUpdateRequest` is the request sent for a `DoUpdate` request.
|
|
|
|
pub struct DoUpdateRequest {
|
|
|
|
#[serde(rename = "edPubkeyPEM")]
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// The new ed25519 public key that should be used for future API requests
|
|
|
|
pub ed_pubkey_pem: Vec<u8>,
|
|
|
|
#[serde(rename = "dhPubkeyPEM")]
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// The new ECDH public key that the Nebula certificate should be signed for
|
|
|
|
pub dh_pubkey_pem: Vec<u8>,
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// A randomized value used to uniquely identify this request.
|
|
|
|
/// The original client uses a randomized, 16-byte value here, which dnapi-rs replicates
|
|
|
|
pub nonce: Vec<u8>
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
/// A server response to a `DoUpdateRequest`, with the updated config and key information
|
|
|
|
pub struct DoUpdateResponse {
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// The base64-encoded Nebula config. It does **NOT** have a private-key, which must be inserted explicitly before Nebula can be ran
|
|
|
|
pub config: Vec<u8>,
|
|
|
|
/// The new config counter. It is unknown what the purpose of this is, but the original client keeps track of it and it is used later in the api
|
|
|
|
pub counter: u32,
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// The same base64-encoded nonce that was sent in the `DoUpdateRequest`.
|
|
|
|
pub nonce: Vec<u8>,
|
|
|
|
#[serde(rename = "trustedKeys")]
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// A new set of trusted ed25519 keys that can be used by the server to sign messages.
|
|
|
|
pub trusted_keys: Vec<u8>
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The REST enrollment endpoint
|
2023-03-29 18:31:07 +00:00
|
|
|
pub const ENROLL_ENDPOINT: &str = "/v2/enroll";
|
2023-03-29 15:18:33 +00:00
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
/// `EnrollRequest` is issued to the `ENROLL_ENDPOINT` to enroll this `dnclient` with a dnapi organization
|
|
|
|
pub struct EnrollRequest {
|
|
|
|
/// The enrollment code given by the API server.
|
|
|
|
pub code: String,
|
|
|
|
#[serde(rename = "dhPubkey")]
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// The ECDH public-key that should be used to sign the Nebula certificate given to this node.
|
|
|
|
pub dh_pubkey: Vec<u8>,
|
|
|
|
#[serde(rename = "edPubkey")]
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// The Ed25519 public-key that this node will use to sign messages sent to the API.
|
|
|
|
pub ed_pubkey: Vec<u8>,
|
|
|
|
/// The timestamp of when this request was sent. Follows the format `%Y-%m-%dT%H:%M:%S.%f%:z`, or:
|
|
|
|
/// <4-digit year>-<two-digit-month>-<two-digit-day>T<two-digit-hour, 24-hour>:<two-digit-minute>:<two-digit-second>.<nanoseconds, zero-padded><offset with semicolon>
|
|
|
|
/// For example:
|
|
|
|
/// `2023-03-29T09:56:42.380006369-04:00`
|
|
|
|
/// would represent `29 March 03, 2023, 09:56:42.380006369 UTC-4`
|
|
|
|
pub timestamp: String
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
#[serde(untagged)]
|
|
|
|
/// The response to an `EnrollRequest`
|
|
|
|
pub enum EnrollResponse {
|
|
|
|
/// A successful enrollment, with a `data` field pointing to an `EnrollResponseData`
|
|
|
|
Success {
|
|
|
|
/// The response data from this response
|
|
|
|
data: EnrollResponseData
|
|
|
|
},
|
|
|
|
/// An unsuccessful enrollment, with an `errors` field pointing to an array of `APIError`s.
|
|
|
|
Error {
|
|
|
|
/// A list of `APIError`s that happened while trying to enroll. `APIErrors` is a type alias to `Vec<APIError>`
|
|
|
|
errors: APIErrors
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
/// The data included in an successful enrollment.
|
|
|
|
pub struct EnrollResponseData {
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// The base64-encoded Nebula config. It does **NOT** have a private-key, which must be inserted explicitly before Nebula can be ran
|
|
|
|
pub config: Vec<u8>,
|
|
|
|
#[serde(rename = "hostID")]
|
|
|
|
/// The server-side Host ID that this node now has.
|
|
|
|
pub host_id: String,
|
|
|
|
/// The new config counter. It is unknown what the purpose of this is, but the original client keeps track of it and it is used later in the api
|
|
|
|
pub counter: u32,
|
|
|
|
#[serde(rename = "trustedKeys")]
|
|
|
|
#[serde(with = "Base64Standard")]
|
|
|
|
/// A new set of trusted ed25519 keys that can be used by the server to sign messages.
|
|
|
|
pub trusted_keys: Vec<u8>,
|
|
|
|
/// The organization data that this node is now a part of
|
|
|
|
pub organization: EnrollResponseDataOrg
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
/// The organization data that this node is now a part of
|
|
|
|
pub struct EnrollResponseDataOrg {
|
|
|
|
/// The organization ID that this node is now a part of
|
|
|
|
pub id: String,
|
|
|
|
/// The name of the organization that this node is now a part of
|
|
|
|
pub name: String
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize)]
|
|
|
|
/// `APIError` represents a single error returned in an API error response.
|
|
|
|
pub struct APIError {
|
|
|
|
/// The error code
|
|
|
|
pub code: String,
|
|
|
|
/// The human-readable error message
|
|
|
|
pub message: String,
|
|
|
|
/// An optional path to where the error occured
|
|
|
|
pub path: Option<String>
|
|
|
|
}
|
|
|
|
|
|
|
|
/// A type alias to a array of `APIErrors`. Just for parity with dnapi.
|
|
|
|
pub type APIErrors = Vec<APIError>;
|