trifid-api 0.3.0-alpha1 and some work on a tfweb rewrite #6
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="trifidapi@localhost" uuid="39c81b89-3fc4-493f-b203-7a00527cffe6">
|
||||
<data-source source="LOCAL" name="trifid@localhost" uuid="39c81b89-3fc4-493f-b203-7a00527cffe6">
|
||||
<driver-ref>postgresql</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||
|
|
|
@ -1025,7 +1025,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "dnapi-rs"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
dependencies = [
|
||||
"base64 0.21.5",
|
||||
"base64-serde",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "dnapi-rs"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
edition = "2021"
|
||||
description = "A rust client for the Defined Networking API"
|
||||
license = "AGPL-3.0-or-later"
|
||||
|
|
|
@ -13,6 +13,7 @@ use log::{debug, error};
|
|||
use reqwest::StatusCode;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::error::Error;
|
||||
use reqwest::header::HeaderValue;
|
||||
use trifid_pki::cert::serialize_ed25519_public;
|
||||
use trifid_pki::ed25519_dalek::{Signature, Signer, SigningKey, Verifier};
|
||||
use url::Url;
|
||||
|
@ -89,10 +90,15 @@ impl Client {
|
|||
.send()
|
||||
.await?;
|
||||
|
||||
let empty_hval;
|
||||
#[allow(clippy::unwrap_used)] {
|
||||
empty_hval = HeaderValue::from_str("").unwrap();
|
||||
};
|
||||
|
||||
let req_id = resp
|
||||
.headers()
|
||||
.get("X-Request-ID")
|
||||
.ok_or("Response missing X-Request-ID")?
|
||||
.unwrap_or(&empty_hval)
|
||||
.to_str()?;
|
||||
debug!("enrollment request complete {{req_id: {}}}", req_id);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ use log::{debug, error, trace};
|
|||
use reqwest::StatusCode;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::error::Error;
|
||||
use reqwest::header::HeaderValue;
|
||||
use trifid_pki::cert::serialize_ed25519_public;
|
||||
use trifid_pki::ed25519_dalek::{Signature, Signer, SigningKey, Verifier};
|
||||
use url::Url;
|
||||
|
@ -90,10 +91,15 @@ impl Client {
|
|||
.body(req_json)
|
||||
.send()?;
|
||||
|
||||
let empty_hval;
|
||||
#[allow(clippy::unwrap_used)] {
|
||||
empty_hval = HeaderValue::from_str("").unwrap();
|
||||
};
|
||||
|
||||
let req_id = resp
|
||||
.headers()
|
||||
.get("X-Request-ID")
|
||||
.ok_or("Response missing X-Request-ID")?
|
||||
.unwrap_or(&empty_hval)
|
||||
.to_str()?;
|
||||
debug!("enrollment request complete {{req_id: {}}}", req_id);
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ fn insert_private_key(instance: &str) -> Result<(), Box<dyn Error>> {
|
|||
|
||||
config.pki.key = Some(String::from_utf8(key)?);
|
||||
|
||||
debug!("inserted private key into config: {:?}", config);
|
||||
debug!("inserted private key into config");
|
||||
|
||||
let config_str = serde_yaml::to_string(&config)?;
|
||||
fs::write(nebula_yml(instance), config_str)?;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::models::SessionToken;
|
||||
use crate::models::{AuthToken, SessionToken};
|
||||
|
||||
pub struct AuthInfo {
|
||||
pub session_token: Option<SessionToken>,
|
||||
pub auth_token: Option<()>,
|
||||
pub auth_token: Option<AuthToken>,
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
|
@ -52,7 +52,24 @@ macro_rules! auth {
|
|||
auth_info.session_token = Some(real_token.clone());
|
||||
} else if token.starts_with("auth-") {
|
||||
// parse auth token
|
||||
todo!()
|
||||
|
||||
use $crate::schema::auth_tokens::dsl::*;
|
||||
|
||||
let tokens = $crate::handle_error!(
|
||||
auth_tokens
|
||||
.filter(id.eq(token))
|
||||
.select($crate::models::AuthToken::as_select())
|
||||
.load(&mut $c)
|
||||
.await
|
||||
);
|
||||
let real_token = match tokens.get(0) {
|
||||
Some(tok) => tok,
|
||||
None => $crate::err!(
|
||||
actix_web::http::StatusCode::UNAUTHORIZED,
|
||||
$crate::make_err!("ERR_UNAUTHORIZED", "unauthorized")
|
||||
),
|
||||
};
|
||||
auth_info.auth_token = Some(real_token.clone());
|
||||
}
|
||||
}
|
||||
auth_info
|
||||
|
|
|
@ -65,7 +65,7 @@ pub async fn generate_config(
|
|||
let mut ca_string = String::new();
|
||||
|
||||
for ca in cas {
|
||||
if ca.expires_at < SystemTime::now() {
|
||||
if ca.expires_at > SystemTime::now() {
|
||||
let ca_cert: NebulaCertificate =
|
||||
serde_json::from_value(ca.cert.clone()).map_err(ConfigGenError::InvalidCACert)?;
|
||||
ca_string += &String::from_utf8_lossy(
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::config::Config;
|
|||
use crate::error::APIErrorResponse;
|
||||
use actix_web::middleware::Logger;
|
||||
use actix_web::web::{Data, JsonConfig};
|
||||
use actix_web::dev::Service;
|
||||
use actix_web::{App, Error, HttpResponse, HttpServer};
|
||||
use diesel::Connection;
|
||||
use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
|
||||
|
@ -12,6 +13,8 @@ use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
|
|||
use log::{error, info};
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use actix_web::http::header::{HeaderName, HeaderValue};
|
||||
use std::str::FromStr;
|
||||
|
||||
pub mod error;
|
||||
#[macro_use]
|
||||
|
@ -138,10 +141,22 @@ async fn main() {
|
|||
.service(routes::v1::auth::verify_magic_link::verify_link_req)
|
||||
.service(routes::v1::auth::magic_link::login_req)
|
||||
.service(routes::v1::totp_authenticators::create_totp_auth_req)
|
||||
.service(routes::v1::verify_totp_authenticator::verify_totp_req)
|
||||
.service(routes::v1::verify_totp_authenticators::verify_totp_req)
|
||||
.service(routes::v1::auth::totp::totp_req)
|
||||
.service(routes::v1::dnclient::dnclient_req)
|
||||
.service(routes::v1::networks::create_network_req)
|
||||
.service(routes::v2::enroll::enroll_req)
|
||||
.wrap(Logger::default())
|
||||
.wrap(actix_cors::Cors::permissive())
|
||||
.wrap_fn(|req, srv| {
|
||||
let fut = srv.call(req);
|
||||
async {
|
||||
let mut res = fut.await?;
|
||||
res.headers_mut()
|
||||
.insert(HeaderName::from_str("X-Request-ID").unwrap(), HeaderValue::from_str(&randid!(id "")).unwrap());
|
||||
Ok(res)
|
||||
}
|
||||
})
|
||||
.app_data(app_state.clone())
|
||||
})
|
||||
.bind((local_config.server.bind.ip, local_config.server.bind.port))
|
||||
|
|
|
@ -16,18 +16,22 @@ use dnapi_rs::message::{
|
|||
use log::warn;
|
||||
use serde::Serialize;
|
||||
use std::time::SystemTime;
|
||||
use actix_web::post;
|
||||
use trifid_pki::cert::{
|
||||
deserialize_ed25519_public, deserialize_x25519_public, serialize_ed25519_public,
|
||||
};
|
||||
use trifid_pki::ed25519_dalek::{Signature, Verifier, VerifyingKey};
|
||||
use trifid_pki::x25519_dalek::PublicKey;
|
||||
use crate::crypt::DnclientKeyLockbox;
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
#[serde(untagged)]
|
||||
pub enum DnclientResponse {
|
||||
CheckForUpdateResp(CheckForUpdateResponseWrapper),
|
||||
DoUpdateResp(SignedResponseWrapper),
|
||||
}
|
||||
|
||||
#[post("/v1/dnclient")]
|
||||
pub async fn dnclient_req(
|
||||
req: Json<RequestV1>,
|
||||
state: Data<AppState>,
|
||||
|
@ -53,7 +57,7 @@ pub async fn dnclient_req(
|
|||
.await
|
||||
.optional());
|
||||
|
||||
let key = match maybe_key {
|
||||
let host_key = match maybe_key {
|
||||
Some(k) => k,
|
||||
None => {
|
||||
err!(
|
||||
|
@ -67,8 +71,9 @@ pub async fn dnclient_req(
|
|||
};
|
||||
|
||||
let signature = handle_error!(Signature::from_slice(&req.signature));
|
||||
let ed_pub = deserialize_ed25519_public(&host_key.client_ed_pub).unwrap();
|
||||
let key = handle_error!(VerifyingKey::from_bytes(
|
||||
&key.client_ed_pub.try_into().unwrap()
|
||||
&ed_pub.try_into().unwrap()
|
||||
));
|
||||
|
||||
if key.verify(req.message.as_bytes(), &signature).is_err() {
|
||||
|
@ -139,7 +144,7 @@ pub async fn dnclient_req(
|
|||
id: randid!(id "hostkey"),
|
||||
host_id: host.id.clone(),
|
||||
counter: new_counter,
|
||||
client_ed_pub: new_ed_key,
|
||||
client_ed_pub: do_update_req.ed_pubkey_pem,
|
||||
client_dh_pub: new_dh_pub_bytes,
|
||||
client_cert: new_config.pki.cert.as_bytes().to_vec(),
|
||||
salt: key_lockbox.nonce.clone(),
|
||||
|
@ -176,10 +181,16 @@ pub async fn dnclient_req(
|
|||
|
||||
let msg_bytes = handle_error!(serde_json::to_vec(&msg));
|
||||
|
||||
let old_key_lockbox = DnclientKeyLockbox {
|
||||
nonce: host_key.salt.clone(),
|
||||
info: host_key.info.clone(),
|
||||
key: host_key.server_ed_priv.clone()
|
||||
};
|
||||
|
||||
let resp = SignedResponse {
|
||||
version: 1,
|
||||
message: msg_bytes.clone(),
|
||||
signature: sign_dnclient_with_lockbox(&key_lockbox, &msg_bytes, &state.config)
|
||||
signature: sign_dnclient_with_lockbox(&old_key_lockbox, &msg_bytes, &state.config)
|
||||
.unwrap().to_vec(),
|
||||
};
|
||||
|
||||
|
|
|
@ -3,4 +3,4 @@ pub mod dnclient;
|
|||
pub mod networks;
|
||||
pub mod signup;
|
||||
pub mod totp_authenticators;
|
||||
pub mod verify_totp_authenticator;
|
||||
pub mod verify_totp_authenticators;
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::schema::signing_cas::dsl::signing_cas;
|
|||
use crate::schema::users;
|
||||
use crate::{auth, enforce, randid, AppState};
|
||||
use actix_web::web::{Data, Json};
|
||||
use actix_web::HttpRequest;
|
||||
use actix_web::{HttpRequest, post};
|
||||
use chrono::{DateTime, SecondsFormat, Utc};
|
||||
use diesel::{ExpressionMethods, QueryDsl, SelectableHelper};
|
||||
use diesel_async::RunQueryDsl;
|
||||
|
@ -25,6 +25,7 @@ pub struct CreateNetworkResp {
|
|||
pub data: NetworkNormalized,
|
||||
}
|
||||
|
||||
#[post("/v1/networks")]
|
||||
pub async fn create_network_req(
|
||||
req: Json<CreateNetworkReq>,
|
||||
state: Data<AppState>,
|
||||
|
|
|
@ -33,7 +33,7 @@ pub struct TotpAuthResp {
|
|||
pub metadata: TotpAuthRespMeta,
|
||||
}
|
||||
|
||||
#[post("/v1/verify-totp-authenticator")]
|
||||
#[post("/v1/verify-totp-authenticators")]
|
||||
pub async fn verify_totp_req(
|
||||
req: Json<VerifyTotpAuthReq>,
|
||||
state: Data<AppState>,
|
|
@ -12,9 +12,11 @@ use diesel::{ExpressionMethods, OptionalExtension, QueryDsl};
|
|||
use diesel_async::RunQueryDsl;
|
||||
use dnapi_rs::message::{EnrollRequest, EnrollResponse, EnrollResponseData, EnrollResponseDataOrg};
|
||||
use std::time::SystemTime;
|
||||
use trifid_pki::cert::serialize_ed25519_public;
|
||||
use actix_web::post;
|
||||
use trifid_pki::cert::{deserialize_x25519_public, serialize_ed25519_public};
|
||||
use trifid_pki::x25519_dalek::PublicKey;
|
||||
|
||||
#[post("/v2/enroll")]
|
||||
pub async fn enroll_req(
|
||||
req: Json<EnrollRequest>,
|
||||
state: Data<AppState>,
|
||||
|
@ -84,7 +86,9 @@ pub async fn enroll_req(
|
|||
|
||||
let (key_lockbox, trusted_key) = handle_error!(create_dnclient_ed_key(&state.config));
|
||||
|
||||
let fixed_dh_key: [u8; 32] = req.dh_pubkey.clone().try_into().unwrap();
|
||||
let dh_pubkey = deserialize_x25519_public(&req.dh_pubkey).unwrap();
|
||||
|
||||
let fixed_dh_key: [u8; 32] = dh_pubkey.clone().try_into().unwrap();
|
||||
|
||||
let user_dh_key = PublicKey::from(fixed_dh_key);
|
||||
|
||||
|
|
Loading…
Reference in New Issue