Create user using kanidm
This commit is contained in:
parent
918a906b64
commit
edcce5e05b
4
.env
4
.env
@ -7,7 +7,7 @@ ORDER_DATABASE_URL=postgres://postgres@localhost/myco_orders
|
||||
TOKEN_DATABASE_URL=postgres://postgres@localhost/myco_tokens
|
||||
|
||||
PASS_SALT=18CHwV7eGFAea16z+qMKZg
|
||||
RUST_LOG=debug
|
||||
RUST_LOG=hyper=error,debug
|
||||
SESSION_SECRET="NEPJs#8jjn8SK8GC7QEC^*P844UgsyEbQB8mRWXkT%3mPrwewZoc25MMby9H#R*w2KzaQgMkk#Pif$kxrLy*N5L!Ch%jxbWoa%gb"
|
||||
JWT_SECRET="42^iFq&ZnQbUf!hwGWXd&CpyY6QQyJmkPU%esFCvne5&Ejcb3nJ4&GyHZp!MArZLf^9*5c6!!VgM$iZ8T%d#&bWTi&xbZk2S@4RN"
|
||||
SIGNATURE=David
|
||||
@ -38,3 +38,5 @@ SONIC_SEARCH_PASS=SecretPassword
|
||||
SONIC_INGEST_ADDR=[::1]:1491
|
||||
SONIC_INGEST_PASS=SecretPassword
|
||||
SEARCH_ACTIVE=true
|
||||
|
||||
KANIDM_IDM_ADMIN_PASS=2MScM5Cr2ANyLRps4ccGZjSJdx8bth6yXEwKJDqYU5ZdNfKN
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,3 +7,4 @@ web/dist
|
||||
web/tmp
|
||||
adapters
|
||||
plugins
|
||||
.env
|
||||
|
758
Cargo.lock
generated
758
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@ members = [
|
||||
"crates/testx",
|
||||
"crates/db-utils",
|
||||
# actors
|
||||
# "crates/account_manager",
|
||||
"crates/account_manager",
|
||||
# "crates/cart_manager",
|
||||
# "crates/database_manager",
|
||||
# "crates/email_manager",
|
||||
|
@ -53,7 +53,6 @@ db_path = "/data/kanidm.db"
|
||||
|
||||
tls_chain = "/data/ca.pem"
|
||||
tls_key = "/data/ca.key"
|
||||
verify_ca = false
|
||||
|
||||
#
|
||||
# The log level of the server. May be one of info, debug, trace
|
||||
@ -61,7 +60,7 @@ verify_ca = false
|
||||
# NOTE: this can be overridden by the environment variable
|
||||
# `KANIDM_LOG_LEVEL` at runtime
|
||||
# Defaults to "info"
|
||||
# log_level = "info"
|
||||
log_level = "info"
|
||||
#
|
||||
# The DNS domain name of the server. This is used in a
|
||||
# number of security-critical contexts
|
||||
|
@ -16,6 +16,8 @@ dotenv = { version = "0" }
|
||||
futures = { version = "0" }
|
||||
gumdrop = { version = "0" }
|
||||
json = { version = "0" }
|
||||
kanidm_client = "1.2.2"
|
||||
kanidm_proto = "1.2.2"
|
||||
model = { path = "../model", features = ['db'] }
|
||||
rumqttc = { version = "*" }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
@ -25,6 +27,7 @@ tarpc = { version = "0", features = ["tokio1", "serde-transport-bincode", "serde
|
||||
thiserror = { version = "1" }
|
||||
tokio = { version = "1", features = ['full'] }
|
||||
tracing = { version = "0" }
|
||||
uuid = { workspace = true, features = ["v4"] }
|
||||
|
||||
[dev-dependencies]
|
||||
fake = { version = "2" }
|
||||
|
@ -4,8 +4,7 @@ pub mod addresses;
|
||||
pub use accounts::*;
|
||||
pub use addresses::*;
|
||||
use config::SharedAppConfig;
|
||||
use sqlx_core::pool::Pool;
|
||||
use sqlx_core::postgres::Postgres;
|
||||
use sqlx::{Pool, Postgres};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Database {
|
||||
|
126
crates/account_manager/src/idp.rs
Normal file
126
crates/account_manager/src/idp.rs
Normal file
@ -0,0 +1,126 @@
|
||||
use kanidm_client::{ClientError, KanidmClient};
|
||||
use kanidm_proto::internal::CUStatus;
|
||||
use kanidm_proto::v1::Entry;
|
||||
|
||||
pub async fn refresh_token(kanidm: &KanidmClient) -> Result<(), ClientError> {
|
||||
kanidm
|
||||
.auth_simple_password(
|
||||
"idm_admin",
|
||||
&std::env::var("KANIDM_IDM_ADMIN_PASS")
|
||||
.expect("idm_admin password is requied, please set KANIDM_IDM_ADMIN_PASS"),
|
||||
)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn create_account_with_password(
|
||||
kanidm: &KanidmClient,
|
||||
login: &str,
|
||||
display_name: &str,
|
||||
email: &str,
|
||||
password: &str,
|
||||
) -> Result<(), ClientError> {
|
||||
refresh_token(kanidm).await?;
|
||||
let _person_created = kanidm
|
||||
.idm_person_account_create(login, display_name)
|
||||
.await
|
||||
.ok();
|
||||
let accounts = accounts(kanidm).await?;
|
||||
let uid = find_account(&accounts, FindBy::Name(login)).await?;
|
||||
let id = uid.to_string();
|
||||
|
||||
kanidm
|
||||
.idm_person_account_update(&id, None, None, None, Some(&[email.to_string()]))
|
||||
.await?;
|
||||
let (session_token, status) = kanidm.idm_account_credential_update_begin(&id).await?;
|
||||
tracing::debug!(
|
||||
"Begin update credentials ({can_commit}): {status:?}",
|
||||
can_commit = status.can_commit
|
||||
);
|
||||
|
||||
kanidm
|
||||
.idm_account_credential_update_set_password(&session_token, password)
|
||||
.await?;
|
||||
|
||||
let status = kanidm
|
||||
.idm_account_credential_update_status(&session_token)
|
||||
.await?;
|
||||
tracing::debug!(
|
||||
"Set password ({can_commit}): {status:?}",
|
||||
can_commit = status.can_commit
|
||||
);
|
||||
|
||||
let status = kanidm
|
||||
.idm_account_credential_update_init_totp(&session_token)
|
||||
.await?;
|
||||
tracing::debug!(
|
||||
"Init TOTP ({can_commit}): {status:?}",
|
||||
can_commit = status.can_commit
|
||||
);
|
||||
|
||||
// let status = kanidm
|
||||
// .idm_account_credential_update_check_totp(&session_token, totp_chal,
|
||||
// label) .await?;
|
||||
|
||||
tracing::debug!(
|
||||
"TOTP check ({can_commit}): {status:?}",
|
||||
can_commit = status.can_commit
|
||||
);
|
||||
|
||||
kanidm
|
||||
.idm_account_credential_update_commit(&session_token)
|
||||
.await?;
|
||||
let status = kanidm
|
||||
.idm_account_credential_update_status(&session_token)
|
||||
.await?;
|
||||
tracing::debug!(
|
||||
"Commit ({can_commit}): {status:?}",
|
||||
can_commit = status.can_commit
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn accounts(kanidm: &KanidmClient) -> Result<Vec<Entry>, ClientError> {
|
||||
refresh_token(kanidm).await?;
|
||||
|
||||
kanidm.idm_person_account_list().await
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FindBy<'s> {
|
||||
Email(&'s str),
|
||||
Name(&'s str),
|
||||
}
|
||||
|
||||
impl<'s> FindBy<'s> {
|
||||
fn key(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Email(..) => "mail",
|
||||
Self::Name(..) => "name",
|
||||
}
|
||||
}
|
||||
fn as_str(&self) -> &'s str {
|
||||
match self {
|
||||
Self::Email(s) => s,
|
||||
Self::Name(s) => s,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn find_account(list: &[Entry], find_by: FindBy<'_>) -> Result<uuid::Uuid, ClientError> {
|
||||
list.iter()
|
||||
.find_map(|entra| {
|
||||
tracing::debug!("compare {find_by:?} with {entra:?}");
|
||||
let attrs = &entra.attrs;
|
||||
attrs.get(find_by.key()).filter(|v| {
|
||||
tracing::debug!("compare value {v:?} with {s}", s = find_by.as_str());
|
||||
v.iter().any(|s| s == find_by.as_str())
|
||||
})?;
|
||||
let id = attrs.get("uuid").and_then(|v| v.first())?;
|
||||
id.parse::<uuid::Uuid>().ok()
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
tracing::info!("User not found");
|
||||
ClientError::Unauthorized
|
||||
})
|
||||
}
|
@ -4,6 +4,7 @@ use config::UpdateConfig;
|
||||
|
||||
pub mod actions;
|
||||
pub mod db;
|
||||
pub mod idp;
|
||||
pub mod mqtt;
|
||||
pub mod rpc;
|
||||
|
||||
@ -38,6 +39,23 @@ async fn main() {
|
||||
|
||||
let db = db::Database::build(config.clone()).await;
|
||||
|
||||
let kanidm = kanidm_client::KanidmClientBuilder::new()
|
||||
.address(config.lock().account_manager().idm_url().to_owned())
|
||||
.danger_accept_invalid_certs(cfg!(debug_assertions))
|
||||
.connect_timeout(2)
|
||||
.build()
|
||||
.unwrap();
|
||||
idp::accounts(&kanidm).await.unwrap();
|
||||
idp::create_account_with_password(
|
||||
&kanidm,
|
||||
"eraden",
|
||||
"Adrian Woźniak",
|
||||
"adrian.wozniak@ita-prog.pl",
|
||||
"n59GmOOdcpVUJqJ1",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let mqtt_client = mqtt::start(config.clone(), db.clone()).await;
|
||||
rpc::start(config.clone(), db.clone(), mqtt_client.clone()).await;
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ struct AccountsServer {
|
||||
mqtt_client: AsyncClient,
|
||||
}
|
||||
|
||||
#[tarpc::server]
|
||||
impl Accounts for AccountsServer {
|
||||
async fn me(self, _: context::Context, input: me::Input) -> me::Output {
|
||||
let res = actions::me(input.account_id, self.db).await;
|
||||
|
@ -8,10 +8,9 @@ use tarpc::tokio_serde::formats::Bincode;
|
||||
|
||||
pub async fn start<Server, Req, Build>(name: &str, port: u16, build: Build)
|
||||
where
|
||||
Server: Serve<Req> + Send + 'static + Clone,
|
||||
Server: Serve<Req = Req> + Send + 'static + Clone,
|
||||
Build: Fn() -> Server,
|
||||
<Server as Serve<Req>>::Fut: Send,
|
||||
<Server as Serve<Req>>::Resp: serde::Serialize + Send + 'static,
|
||||
Server::Resp: serde::Serialize + Send + 'static,
|
||||
Req: Send + 'static,
|
||||
Req: for<'l> serde::Deserialize<'l>,
|
||||
{
|
||||
@ -33,7 +32,7 @@ where
|
||||
// the generated World trait.
|
||||
.map(|channel| channel.execute(build()))
|
||||
// Max 10 channels.
|
||||
.buffer_unordered(10)
|
||||
// .buffer_unordered(10)
|
||||
.for_each(|_| async {})
|
||||
.await;
|
||||
tracing::info!("RPC channel closed");
|
||||
|
@ -354,6 +354,7 @@ pub struct AccountManagerConfig {
|
||||
pub mqtt_port: u16,
|
||||
pub mqtt_bind: String,
|
||||
pub database_url: String,
|
||||
pub idm_url: String,
|
||||
}
|
||||
|
||||
impl Default for AccountManagerConfig {
|
||||
@ -364,6 +365,7 @@ impl Default for AccountManagerConfig {
|
||||
mqtt_port: 1883,
|
||||
mqtt_bind: "0.0.0.0".into(),
|
||||
database_url: "postgres://postgres@localhost/myco_accounts".into(),
|
||||
idm_url: "https://localhost:8443".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -378,6 +380,10 @@ impl AccountManagerConfig {
|
||||
pub fn mqtt_addr(&self) -> (&str, u16) {
|
||||
(&self.mqtt_bind, self.mqtt_port)
|
||||
}
|
||||
|
||||
pub fn idm_url(&self) -> &str {
|
||||
&self.idm_url
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
@ -149,7 +149,7 @@ impl From<(crate::Order, Vec<crate::OrderItem>)> for Order {
|
||||
checkout_notes,
|
||||
address_id,
|
||||
},
|
||||
mut items,
|
||||
items,
|
||||
): (crate::Order, Vec<crate::OrderItem>),
|
||||
) -> Self {
|
||||
Order {
|
||||
|
@ -10,7 +10,13 @@ services:
|
||||
ports:
|
||||
- 636:3636
|
||||
- 443:8443
|
||||
- 8443:8443
|
||||
- 8400:80
|
||||
rumqqtd:
|
||||
image: bytebeamio/rumqttd
|
||||
ports:
|
||||
- 1883:1883
|
||||
- 1884:1884
|
||||
quickwit:
|
||||
image: quickwit/quickwit:v0.5.2
|
||||
command: run
|
||||
|
90
myco.toml
Normal file
90
myco.toml
Normal file
@ -0,0 +1,90 @@
|
||||
[account_manager]
|
||||
rpc_port = 19329
|
||||
rpc_bind = "0.0.0.0"
|
||||
mqtt_port = 1883
|
||||
mqtt_bind = "0.0.0.0"
|
||||
database_url = "postgres://postgres@localhost/myco_accounts"
|
||||
idm_url = "https://localhost:8443"
|
||||
|
||||
[cart_manager]
|
||||
rpc_port = 19330
|
||||
rpc_bind = "0.0.0.0"
|
||||
mqtt_port = 1884
|
||||
mqtt_bind = "0.0.0.0"
|
||||
database_url = "postgres://postgres@localhost/myco_carts"
|
||||
|
||||
[database]
|
||||
url = "postgres://postgres@localhost/myco"
|
||||
|
||||
[email_sender]
|
||||
rpc_port = 19331
|
||||
rpc_bind = "0.0.0.0"
|
||||
mqtt_port = 1885
|
||||
mqtt_bind = "0.0.0.0"
|
||||
database_url = "postgres://postgres@localhost/myco_emails"
|
||||
|
||||
[files]
|
||||
public_path = "/uploads"
|
||||
local_path = "/var/local/myco"
|
||||
|
||||
[mail]
|
||||
sendgrid_secret = "Create sendgrid account and copy credentials here"
|
||||
sendgrid_api_key = "Create sendgrid account and copy credentials here"
|
||||
smtp_from = "Valid sendgrid authorized email address. Example: contact@example.com"
|
||||
|
||||
[order_manager]
|
||||
rpc_port = 19334
|
||||
rpc_bind = "0.0.0.0"
|
||||
mqtt_port = 1887
|
||||
mqtt_bind = "0.0.0.0"
|
||||
database_url = "postgres://postgres@localhost/myco_orders"
|
||||
|
||||
[payment]
|
||||
rpc_port = 19335
|
||||
rpc_bind = "0.0.0.0"
|
||||
mqtt_port = 1888
|
||||
mqtt_bind = "0.0.0.0"
|
||||
adapters_path = "./adapters"
|
||||
optional_payment = true
|
||||
|
||||
[payment.pay_u]
|
||||
client_id = "Create payu account and copy here client_id"
|
||||
client_secret = "Create payu account and copy here client_secret"
|
||||
merchant_id = "Create payu account and copy here merchant id"
|
||||
example2 = "custom value2"
|
||||
example1 = "custom value1"
|
||||
|
||||
[search]
|
||||
sonic_search_addr = "[::1]:1491"
|
||||
sonic_search_pass = "SecretPassword"
|
||||
sonic_ingest_addr = "[::1]:1491"
|
||||
sonic_ingest_pass = "SecretPassword"
|
||||
rpc_port = 19332
|
||||
rpc_bind = "0.0.0.0"
|
||||
search_active = true
|
||||
|
||||
[stocks]
|
||||
rpc_port = 19333
|
||||
rpc_bind = "0.0.0.0"
|
||||
mqtt_port = 1886
|
||||
mqtt_bind = "0.0.0.0"
|
||||
database_url = "postgres://postgres@localhost/myco_stocks"
|
||||
|
||||
[tokens]
|
||||
rpc_port = 19336
|
||||
rpc_bind = "0.0.0.0"
|
||||
mqtt_port = 1889
|
||||
mqtt_bind = "0.0.0.0"
|
||||
database_url = "postgres://postgres@localhost/myco_tokens"
|
||||
|
||||
[web]
|
||||
host = "https://your.comain.com"
|
||||
pass_salt = "Generate it with myco generate-hash"
|
||||
session_secret = "100 characters long random string"
|
||||
jwt_secret = "100 characters long random string"
|
||||
bind = "0.0.0.0"
|
||||
port = 8080
|
||||
signature = "John Doe"
|
||||
service_name = "myco"
|
||||
|
||||
[plugin]
|
Loading…
Reference in New Issue
Block a user