work
This commit is contained in:
parent
2045d7b636
commit
d44a6c1166
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
<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>
|
<driver-ref>postgresql</driver-ref>
|
||||||
<synchronize>true</synchronize>
|
<synchronize>true</synchronize>
|
||||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
<sourceFolder url="file://$MODULE_DIR$/trifid-api-old/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/trifid-api-old/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/trifid-api-old/trifid_api_entities/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/trifid-api-old/trifid_api_entities/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/trifid-api-old/trifid_api_migration/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/trifid-api-old/trifid_api_migration/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/trifid-api-derive/src" isTestSource="false" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
|
|
|
@ -211,6 +211,16 @@ version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aead"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aes"
|
name = "aes"
|
||||||
version = "0.8.3"
|
version = "0.8.3"
|
||||||
|
@ -545,6 +555,30 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chacha20"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cipher",
|
||||||
|
"cpufeatures",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chacha20poly1305"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
|
||||||
|
dependencies = [
|
||||||
|
"aead",
|
||||||
|
"chacha20",
|
||||||
|
"cipher",
|
||||||
|
"poly1305",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "checked_int_cast"
|
name = "checked_int_cast"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -574,6 +608,7 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
"inout",
|
"inout",
|
||||||
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -779,6 +814,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
|
"rand_core",
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1867,6 +1903,12 @@ version = "1.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "opaque-debug"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "option-ext"
|
name = "option-ext"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -1998,6 +2040,17 @@ version = "3.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8"
|
checksum = "4503fa043bf02cee09a9582e9554b4c6403b2ef55e4612e96561d294419429f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "poly1305"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
|
||||||
|
dependencies = [
|
||||||
|
"cpufeatures",
|
||||||
|
"opaque-debug",
|
||||||
|
"universal-hash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "postgres-protocol"
|
name = "postgres-protocol"
|
||||||
version = "0.6.6"
|
version = "0.6.6"
|
||||||
|
@ -2721,7 +2774,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tfcli"
|
name = "tfcli"
|
||||||
version = "0.3.0"
|
version = "0.3.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"comfy-table",
|
"comfy-table",
|
||||||
|
@ -3027,17 +3080,29 @@ dependencies = [
|
||||||
"actix-cors",
|
"actix-cors",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"bb8",
|
"bb8",
|
||||||
|
"chacha20poly1305",
|
||||||
"diesel",
|
"diesel",
|
||||||
"diesel-async",
|
"diesel-async",
|
||||||
"diesel_migrations",
|
"diesel_migrations",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"hex",
|
||||||
"log",
|
"log",
|
||||||
"mail-send",
|
"mail-send",
|
||||||
"rand",
|
"rand",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
"toml 0.8.5",
|
"toml 0.8.5",
|
||||||
"totp-rs",
|
"totp-rs",
|
||||||
|
"trifid-pki",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "trifid-api-derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3095,6 +3160,16 @@ version = "0.1.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "universal-hash"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unsafe-libyaml"
|
name = "unsafe-libyaml"
|
||||||
version = "0.2.9"
|
version = "0.2.9"
|
||||||
|
|
|
@ -5,6 +5,9 @@ members = [
|
||||||
"dnapi-rs",
|
"dnapi-rs",
|
||||||
"tfcli",
|
"tfcli",
|
||||||
"nebula-ffi",
|
"nebula-ffi",
|
||||||
"trifid-api"
|
|
||||||
|
"trifid-api",
|
||||||
|
"trifid-api-derive"
|
||||||
]
|
]
|
||||||
|
|
||||||
resolver = "2"
|
resolver = "2"
|
|
@ -0,0 +1,13 @@
|
||||||
|
[package]
|
||||||
|
name = "trifid-api-derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
syn = { version = "2", features = ["full", "fold"] }
|
||||||
|
quote = "1"
|
|
@ -25,4 +25,8 @@ diesel_migrations = "2"
|
||||||
bb8 = "0.8"
|
bb8 = "0.8"
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
mail-send = "0.4"
|
mail-send = "0.4"
|
||||||
totp-rs = { version = "5.4", features = ["gen_secret", "otpauth"] }
|
totp-rs = { version = "5.4", features = ["gen_secret", "otpauth"] }
|
||||||
|
trifid-pki = { version = "0.1", path = "../trifid-pki", features = ["serde_derive"] }
|
||||||
|
chacha20poly1305 = "0.10"
|
||||||
|
hex = "0.4"
|
||||||
|
thiserror = "1"
|
|
@ -25,7 +25,7 @@ server = "mail.e3t.cc"
|
||||||
port = 465
|
port = 465
|
||||||
# (Required) The username to authenticate with.
|
# (Required) The username to authenticate with.
|
||||||
username = "core"
|
username = "core"
|
||||||
# (Required) The password to authenticate with. If set to %PASSWORD%, will be filled from the environment variable TRIFID_EMAIL_PASSWORD.
|
# (Required) The password to authenticate with. If set to $PASSWORD$, will be filled from the environment variable TRIFID_EMAIL_PASSWORD.
|
||||||
password = "$PASSWORD$"
|
password = "$PASSWORD$"
|
||||||
# (Required) The "From Name" to send the email from
|
# (Required) The "From Name" to send the email from
|
||||||
from_name = "Trifid"
|
from_name = "Trifid"
|
||||||
|
@ -45,4 +45,8 @@ magic_link_expiry_seconds = 3600 # 1 hour
|
||||||
session_token_expiry_seconds = 31536000 # ~1 year
|
session_token_expiry_seconds = 31536000 # ~1 year
|
||||||
# (Required) How long should auth tokens be valid for, in seconds? This controls how long users can remain logged in
|
# (Required) How long should auth tokens be valid for, in seconds? This controls how long users can remain logged in
|
||||||
# before they must re-authenticate via 2FA.
|
# before they must re-authenticate via 2FA.
|
||||||
auth_token_expiry_seconds = 86400 # 24 hours
|
auth_token_expiry_seconds = 86400 # 24 hours
|
||||||
|
# (Required) (VERY IMPORTANT!) The per-instance encryption key used to encrypt sensitive data in the database.
|
||||||
|
# It is INCREDIBLY IMPORTANT that you change this value! It should be a 32-byte/256-bit hex-encoded randomly generated
|
||||||
|
# key.
|
||||||
|
data_encryption_key = "dd5aa62f0fd9b7fb4ff65567493f889557212f3a8e9587a79268161f9ae070a6"
|
|
@ -0,0 +1,100 @@
|
||||||
|
use std::error::Error;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
use actix_web::cookie::time::Duration;
|
||||||
|
use chacha20poly1305::{AeadCore, KeyInit, Nonce, XChaCha20Poly1305, XNonce};
|
||||||
|
use chacha20poly1305::aead::{Aead, Payload};
|
||||||
|
use log::error;
|
||||||
|
use rand::Rng;
|
||||||
|
use rand::rngs::OsRng;
|
||||||
|
use thiserror::Error;
|
||||||
|
use crate::models::SigningCA;
|
||||||
|
use trifid_pki::cert::{NebulaCertificate, NebulaCertificateDetails};
|
||||||
|
use trifid_pki::ed25519_dalek::{SignatureError, SigningKey};
|
||||||
|
use crate::config::Config;
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum CryptographyError {
|
||||||
|
#[error("certificate signing error: {0}")]
|
||||||
|
CertificateSigningError(Box<dyn Error>),
|
||||||
|
#[error("PEM serialization error: {0}")]
|
||||||
|
PemSerializeError(Box<dyn Error>),
|
||||||
|
#[error("JSON serialization error: {0}")]
|
||||||
|
JsonSerializeError(serde_json::Error),
|
||||||
|
#[error("Invalid data_encryption_key content: {0}")]
|
||||||
|
InvalidKey(hex::FromHexError),
|
||||||
|
#[error("Invalid data_encryption_key length (must be 32 bytes)")]
|
||||||
|
InvalidKeyLength,
|
||||||
|
#[error("Error locking lockbox")]
|
||||||
|
LockingError,
|
||||||
|
#[error("Invalid salt length")]
|
||||||
|
InvalidSaltLength,
|
||||||
|
#[error("Key material decryption failed")]
|
||||||
|
DecryptFailed,
|
||||||
|
#[error("Invalid signing key length after lockbox unlock")]
|
||||||
|
InvalidSigningKeyLength,
|
||||||
|
#[error("Signature error {0}")]
|
||||||
|
SignatureError(SignatureError)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_signing_ca(expires: SystemTime, org_id: String, user_email: String, config: &Config) -> Result<SigningCA, CryptographyError> {
|
||||||
|
let key = SigningKey::generate(&mut OsRng);
|
||||||
|
|
||||||
|
let mut cert = NebulaCertificate {
|
||||||
|
details: NebulaCertificateDetails {
|
||||||
|
name: format!("Certificate Authority for {user_email}'s Organization"),
|
||||||
|
ips: vec![],
|
||||||
|
subnets: vec![],
|
||||||
|
groups: vec![],
|
||||||
|
not_before: SystemTime::now() - Duration::hours(24),
|
||||||
|
not_after: expires,
|
||||||
|
public_key: key.verifying_key().as_bytes().clone(),
|
||||||
|
is_ca: true,
|
||||||
|
issuer: "".to_string(),
|
||||||
|
},
|
||||||
|
signature: vec![],
|
||||||
|
};
|
||||||
|
cert.sign(&key).map_err(|e| CryptographyError::CertificateSigningError(e))?;
|
||||||
|
|
||||||
|
let pem = cert.serialize_to_pem().map_err(|e| CryptographyError::PemSerializeError(e))?;
|
||||||
|
|
||||||
|
let cert_value = serde_json::to_value(cert).map_err(|e| CryptographyError::JsonSerializeError(e))?;
|
||||||
|
|
||||||
|
let lockbox_key = XChaCha20Poly1305::new_from_slice(&hex::decode(&config.tokens.data_encryption_key).map_err(|e| CryptographyError::InvalidKey(e))?).map_err(|_| CryptographyError::InvalidKeyLength)?;
|
||||||
|
|
||||||
|
let salt = XChaCha20Poly1305::generate_nonce(&mut OsRng);
|
||||||
|
|
||||||
|
let aad: [u8; 16] = OsRng.gen();
|
||||||
|
|
||||||
|
let lockbox = lockbox_key.encrypt(&salt, Payload {
|
||||||
|
msg: &key.to_keypair_bytes(),
|
||||||
|
aad: &aad,
|
||||||
|
}).map_err(|e| CryptographyError::LockingError)?;
|
||||||
|
|
||||||
|
Ok(SigningCA {
|
||||||
|
id: randid!(id "ca"),
|
||||||
|
pem: String::from_utf8(pem).unwrap(),
|
||||||
|
cert: cert_value,
|
||||||
|
expires_at: cert.details.not_after.clone(),
|
||||||
|
organization_id: org_id,
|
||||||
|
salt: salt.as_slice().to_vec(),
|
||||||
|
info: aad.to_vec(),
|
||||||
|
private_key: lockbox,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sign_cert_with_ca(ca: &SigningCA, cert: &mut NebulaCertificate, config: &Config) -> Result<(), CryptographyError> {
|
||||||
|
let lockbox_key = XChaCha20Poly1305::new_from_slice(&hex::decode(&config.tokens.data_encryption_key).map_err(|e| CryptographyError::InvalidKey(e))?).map_err(|_| CryptographyError::InvalidKeyLength)?;
|
||||||
|
|
||||||
|
let salt_u24: [u8; 24] = ca.salt.try_into().map_err(|_| CryptographyError::InvalidSaltLength)?;
|
||||||
|
|
||||||
|
let salt = XNonce::from(salt_u24);
|
||||||
|
|
||||||
|
let plaintext = lockbox_key.decrypt(&salt, Payload {
|
||||||
|
msg: &ca.private_key,
|
||||||
|
aad: &ca.info,
|
||||||
|
}).map_err(|_| CryptographyError::DecryptFailed)?;
|
||||||
|
|
||||||
|
let key = SigningKey::from_keypair_bytes(&plaintext.try_into().map_err(|_| CryptographyError::InvalidSigningKeyLength)?).map_err(|e| CryptographyError::SignatureError(e))?;
|
||||||
|
|
||||||
|
cert.sign(&key).map_err(|e| CryptographyError::CertificateSigningError(e))
|
||||||
|
}
|
|
@ -43,4 +43,5 @@ pub struct ConfigTokens {
|
||||||
pub magic_link_expiry_seconds: u64,
|
pub magic_link_expiry_seconds: u64,
|
||||||
pub session_token_expiry_seconds: u64,
|
pub session_token_expiry_seconds: u64,
|
||||||
pub auth_token_expiry_seconds: u64,
|
pub auth_token_expiry_seconds: u64,
|
||||||
|
pub data_encryption_key: String
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,10 @@ pub mod schema;
|
||||||
pub mod id;
|
pub mod id;
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod email;
|
pub mod email;
|
||||||
|
#[macro_use]
|
||||||
|
pub mod macros;
|
||||||
|
pub mod ca;
|
||||||
|
pub mod crypt;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use diesel::{Associations, Identifiable, Insertable, Queryable, Selectable};
|
use diesel::{Associations, Identifiable, Insertable, Queryable, Selectable};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
#[derive(Queryable, Selectable, Insertable, Identifiable, Debug, PartialEq, Clone)]
|
#[derive(Queryable, Selectable, Insertable, Identifiable, Debug, PartialEq, Clone, Serialize, Deserialize)]
|
||||||
#[diesel(table_name = crate::schema::users)]
|
#[diesel(table_name = crate::schema::users)]
|
||||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
|
@ -11,7 +12,7 @@ pub struct User {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Queryable, Selectable, Insertable, Identifiable, Associations, Debug, PartialEq, Clone,
|
Queryable, Selectable, Insertable, Identifiable, Associations, Debug, PartialEq, Clone, Serialize, Deserialize
|
||||||
)]
|
)]
|
||||||
#[diesel(belongs_to(User))]
|
#[diesel(belongs_to(User))]
|
||||||
#[diesel(table_name = crate::schema::magic_links)]
|
#[diesel(table_name = crate::schema::magic_links)]
|
||||||
|
@ -23,7 +24,7 @@ pub struct MagicLink {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Queryable, Selectable, Insertable, Identifiable, Associations, Debug, PartialEq, Clone,
|
Queryable, Selectable, Insertable, Identifiable, Associations, Debug, PartialEq, Clone, Serialize, Deserialize
|
||||||
)]
|
)]
|
||||||
#[diesel(belongs_to(User))]
|
#[diesel(belongs_to(User))]
|
||||||
#[diesel(table_name = crate::schema::session_tokens)]
|
#[diesel(table_name = crate::schema::session_tokens)]
|
||||||
|
@ -35,7 +36,7 @@ pub struct SessionToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Queryable, Selectable, Insertable, Identifiable, Associations, Debug, PartialEq, Clone,
|
Queryable, Selectable, Insertable, Identifiable, Associations, Debug, PartialEq, Clone, Serialize, Deserialize
|
||||||
)]
|
)]
|
||||||
#[diesel(belongs_to(User))]
|
#[diesel(belongs_to(User))]
|
||||||
#[diesel(table_name = crate::schema::totp_authenticators)]
|
#[diesel(table_name = crate::schema::totp_authenticators)]
|
||||||
|
@ -51,7 +52,7 @@ pub struct TotpAuthenticator {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Queryable, Selectable, Insertable, Identifiable, Associations, Debug, PartialEq, Clone,
|
Queryable, Selectable, Insertable, Identifiable, Associations, Debug, PartialEq, Clone, Serialize, Deserialize
|
||||||
)]
|
)]
|
||||||
#[diesel(belongs_to(User))]
|
#[diesel(belongs_to(User))]
|
||||||
#[diesel(table_name = crate::schema::auth_tokens)]
|
#[diesel(table_name = crate::schema::auth_tokens)]
|
||||||
|
@ -63,7 +64,7 @@ pub struct AuthToken {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Queryable, Selectable, Insertable, Identifiable, Associations, Debug, PartialEq, Clone,
|
Queryable, Selectable, Insertable, Identifiable, Associations, Debug, PartialEq, Clone, Serialize, Deserialize
|
||||||
)]
|
)]
|
||||||
#[diesel(belongs_to(User, foreign_key = owner_id))]
|
#[diesel(belongs_to(User, foreign_key = owner_id))]
|
||||||
#[diesel(table_name = crate::schema::organizations)]
|
#[diesel(table_name = crate::schema::organizations)]
|
||||||
|
@ -86,7 +87,7 @@ id -> Varchar,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Queryable, Selectable, Insertable, Identifiable, Associations, Debug, PartialEq, Clone,
|
Queryable, Selectable, Insertable, Identifiable, Associations, Debug, PartialEq, Clone, Serialize, Deserialize
|
||||||
)]
|
)]
|
||||||
#[diesel(belongs_to(Organization))]
|
#[diesel(belongs_to(Organization))]
|
||||||
#[diesel(table_name = crate::schema::signing_cas)]
|
#[diesel(table_name = crate::schema::signing_cas)]
|
||||||
|
@ -101,6 +102,17 @@ pub struct SigningCA {
|
||||||
pub info: Vec<u8>,
|
pub info: Vec<u8>,
|
||||||
pub private_key: Vec<u8>
|
pub private_key: Vec<u8>
|
||||||
}
|
}
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, Clone, Debug)]
|
||||||
|
pub struct SigningCANormalized {
|
||||||
|
pub id: String,
|
||||||
|
pub pem: String,
|
||||||
|
pub cert: Value,
|
||||||
|
pub expires_at: String,
|
||||||
|
pub organization_id: String,
|
||||||
|
pub salt: Vec<u8>,
|
||||||
|
pub info: Vec<u8>,
|
||||||
|
pub private_key: Vec<u8>
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
id VARCHAR NOT NULL PRIMARY KEY,
|
id VARCHAR NOT NULL PRIMARY KEY,
|
||||||
|
@ -113,7 +125,7 @@ id VARCHAR NOT NULL PRIMARY KEY,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Queryable, Selectable, Insertable, Identifiable, Associations, Debug, PartialEq, Clone,
|
Queryable, Selectable, Insertable, Identifiable, Associations, Debug, PartialEq, Clone
|
||||||
)]
|
)]
|
||||||
#[diesel(belongs_to(Organization))]
|
#[diesel(belongs_to(Organization))]
|
||||||
#[diesel(belongs_to(SigningCA, foreign_key = signing_ca_id))]
|
#[diesel(belongs_to(SigningCA, foreign_key = signing_ca_id))]
|
||||||
|
@ -127,4 +139,14 @@ pub struct Network {
|
||||||
pub created_at: SystemTime,
|
pub created_at: SystemTime,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub lighthouses_as_relays: bool
|
pub lighthouses_as_relays: bool
|
||||||
|
}
|
||||||
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
|
||||||
|
pub struct NetworkNormalized {
|
||||||
|
pub id: String,
|
||||||
|
pub cidr: String,
|
||||||
|
pub organization_id: String,
|
||||||
|
pub signing_ca_id: String,
|
||||||
|
pub created_at: String,
|
||||||
|
pub name: String,
|
||||||
|
pub lighthouses_as_relays: bool
|
||||||
}
|
}
|
|
@ -1,7 +1,14 @@
|
||||||
|
use std::time::{Duration, SystemTime};
|
||||||
use actix_web::HttpRequest;
|
use actix_web::HttpRequest;
|
||||||
use actix_web::web::Json;
|
use actix_web::web::{Data, Json};
|
||||||
use serde::Deserialize;
|
use serde::{Deserialize, Serialize};
|
||||||
use crate::AppState;
|
use crate::{AppState, auth, enforce, randid};
|
||||||
|
use crate::models::{Network, NetworkNormalized, Organization, SigningCA, User};
|
||||||
|
use crate::response::JsonAPIResponse;
|
||||||
|
use diesel::{SelectableHelper, ExpressionMethods, QueryDsl};
|
||||||
|
use diesel_async::RunQueryDsl;
|
||||||
|
use crate::ca::create_signing_ca;
|
||||||
|
use crate::schema::users;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct CreateNetworkReq {
|
pub struct CreateNetworkReq {
|
||||||
|
@ -9,8 +16,45 @@ pub struct CreateNetworkReq {
|
||||||
pub name: String
|
pub name: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug)]
|
||||||
pub struct CreateNetworkResp {
|
pub struct CreateNetworkResp {
|
||||||
|
pub data: NetworkNormalized
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_network_req(req: Json<CreateNetworkReq>, state: Data<AppState>, req_info: HttpRequest)
|
pub async fn create_network_req(req: Json<CreateNetworkReq>, state: Data<AppState>, req_info: HttpRequest) -> JsonAPIResponse<CreateNetworkResp> {
|
||||||
|
let mut conn = handle_error!(state.pool.get().await);
|
||||||
|
|
||||||
|
let auth_info = auth!(req_info, conn);
|
||||||
|
let (session_token, auth_token) = enforce!(sess auth auth_info);
|
||||||
|
|
||||||
|
let user = handle_error!(
|
||||||
|
users::table
|
||||||
|
.find(&session_token.user_id)
|
||||||
|
.first::<User>(&mut conn)
|
||||||
|
.await
|
||||||
|
);
|
||||||
|
|
||||||
|
let new_org = Organization {
|
||||||
|
id: randid!(id "org"),
|
||||||
|
owner_id: user.id.clone(),
|
||||||
|
name: format!("{}'s Organization", user.email),
|
||||||
|
};
|
||||||
|
|
||||||
|
// create 3 signing CAs, to mimic upstream DN functionality
|
||||||
|
|
||||||
|
let ca_oneyear = handle_error!(create_signing_ca(SystemTime::now() + Duration::from_secs(86400 * 365), new_org.id.clone(), user.email.clone(), &state.config));
|
||||||
|
let ca_twoyears = handle_error!(create_signing_ca(SystemTime::now() + Duration::from_secs(86400 * 365 * 2), new_org.id.clone(), user.email.clone(), &state.config));
|
||||||
|
let ca_threeyears = handle_error!(create_signing_ca(SystemTime::now() + Duration::from_secs(86400 * 365 * 3), new_org.id.clone(), user.email.clone(), &state.config));
|
||||||
|
|
||||||
|
let new_network = Network {
|
||||||
|
id: randid!(id "net"),
|
||||||
|
cidr: req.0.cidr.clone(),
|
||||||
|
organization_id: new_org.id.clone(),
|
||||||
|
signing_ca_id: "".to_string(),
|
||||||
|
created_at: SystemTime::now(),
|
||||||
|
name: "".to_string(),
|
||||||
|
lighthouses_as_relays: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
todo!()
|
||||||
|
}
|
Loading…
Reference in New Issue