diff --git a/README.md b/README.md index 0f4762a..b7c949a 100644 --- a/README.md +++ b/README.md @@ -179,13 +179,76 @@ Errors: ```json {"result": "error", "error": "no valid key"} ``` - #### Success ```json {"result": "success", "success": "key valid"} ``` +### POST /ldap/ssh +Returns array of SSH keys associated with the Skynet account +```json +{ + "auth" : { + "user": "username", + "pass": "password" + } +} +``` +#### Errors +```json +{"result": "error", "error": "Failed to authenticate"} +``` +#### Success +```json +{"result": "success", "success": ["key1","key2","key3"]} +``` + +### DELETE /ldap/ssh +Deletes SSH key from Skynet account +```json +{ + "auth" : { + "user": "username", + "pass": "password" + }, + "key": "ssh key" +} +``` +#### Errors +```json +{"result": "error", "error": "Failed to authenticate"} +``` +```json +{"result": "error", "error": "Failed to remove key"} +``` +#### Success +```json +{"result": "success"} +``` + +### POST /ldap/ssh/add +Adds SSH key to Skynet account +```json +{ + "auth" : { + "user": "username", + "pass": "password" + }, + "key": "ssh key" +} +``` +#### Errors +```json +{"result": "error", "error": "Failed to authenticate"} +``` +```json +{"result": "error", "error": "Failed to add key"} +``` +#### Success +```json +{"result": "success"} +``` ## Responses Generic responses which is used unless otherwise specified above. diff --git a/src/main.rs b/src/main.rs index 262d918..b3ffb03 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ use skynet_ldap_backend::{ db_init, get_config, - methods::{account_new, account_recover, account_update}, + methods::{account_new, account_recover, account_ssh, account_update}, State, }; @@ -34,6 +34,11 @@ async fn main() -> tide::Result<()> { app.at("/ldap/recover/ssh/request").post(account_recover::ssh::request); app.at("/ldap/recover/ssh/verify").post(account_recover::ssh::verify); + //for getting current ssh keys associated with the account + app.at("/ldap/ssh").post(account_ssh::get_ssh_keys); + app.at("/ldap/ssh").delete(account_ssh::remove_ssh_key); + app.at("/ldap/ssh/add").post(account_ssh::add_ssh_key); + app.listen(host_port).await?; Ok(()) } diff --git a/src/methods/account_ssh.rs b/src/methods/account_ssh.rs new file mode 100644 index 0000000..1d6b8fd --- /dev/null +++ b/src/methods/account_ssh.rs @@ -0,0 +1,109 @@ +use crate::{LdapAuth, LdapAuthResult, State}; +use ldap3::{Mod, Scope, SearchEntry}; +use std::collections::HashSet; +use tide::{ + prelude::{json, Deserialize}, + Request, +}; + +#[derive(Debug, Deserialize)] +struct SSHKey { + auth: LdapAuth, + key: String, +} + +pub async fn add_ssh_key(mut req: Request) -> tide::Result { + let SSHKey { + auth, + key, + } = req.body_json().await?; + let config = &req.state().config; + + let LdapAuthResult { + mut ldap, + dn, + .. + } = match crate::auth_user(&auth, config).await { + None => return Ok(json!({"result": "error", "error": "Failed to authenticate"}).into()), + Some(x) => x, + }; + + let mods = vec![Mod::Add("sshPublicKey".to_owned(), HashSet::from([key]))]; + let result = match ldap.modify(&dn, mods) { + Ok(_) => Ok(json!({"result": "success"}).into()), + Err(e) => { + dbg!(e); + Ok(json!({"result": "error", "error": "Failed to add key"}).into()) + } + }; + + ldap.unbind()?; + + result +} + +pub async fn remove_ssh_key(mut req: Request) -> tide::Result { + let SSHKey { + auth, + key, + } = req.body_json().await?; + let config = &req.state().config; + + let LdapAuthResult { + mut ldap, + dn, + .. + } = match crate::auth_user(&auth, config).await { + None => return Ok(json!({"result": "error", "error": "Failed to authenticate"}).into()), + Some(x) => x, + }; + + let mods = vec![Mod::Delete("sshPublicKey".to_owned(), HashSet::from([key]))]; + + let result = match ldap.modify(&dn, mods) { + Ok(_) => Ok(json!({"result": "success"}).into()), + Err(e) => { + dbg!(e); + Ok(json!({"result": "error", "error": "Failed to remove key"}).into()) + } + }; + + ldap.unbind()?; + + result +} + +#[derive(Debug, Deserialize)] +struct SSHKeyGet { + auth: LdapAuth, +} + +pub async fn get_ssh_keys(mut req: Request) -> tide::Result { + let SSHKeyGet { + auth, + } = req.body_json().await?; + let config = &req.state().config; + + let LdapAuthResult { + mut ldap, + dn, + .. + } = match crate::auth_user(&auth, config).await { + None => return Ok(json!({"result": "error", "error": "Failed to authenticate"}).into()), + Some(x) => x, + }; + let mut keys: Vec = vec![]; + let (rs, _res) = ldap.search(&dn, Scope::Base, "(objectClass=*)", vec!["sshPublicKey"])?.success()?; + for entry in rs { + let tmp = SearchEntry::construct(entry); + if tmp.attrs.contains_key("sshPublicKey") { + for key in tmp.attrs["sshPublicKey"].clone() { + keys.push(key); + } + } + } + + ldap.unbind()?; + + Ok(json!({"result": "success", "success": keys}).into()) +} diff --git a/src/methods/mod.rs b/src/methods/mod.rs index 8273b7b..0968f44 100644 --- a/src/methods/mod.rs +++ b/src/methods/mod.rs @@ -1,3 +1,4 @@ pub mod account_new; pub mod account_recover; +pub mod account_ssh; pub mod account_update;