From 0091f148b5b62abf265b8efffac8ec5f22a17f3b Mon Sep 17 00:00:00 2001 From: Louis Vallat Date: Fri, 11 Feb 2022 23:53:43 +0100 Subject: [PATCH] Initial commit: interaction with OVH API Signed-off-by: Louis Vallat --- .gitignore | 2 ++ Cargo.toml | 18 ++++++++++++++++++ src/main.rs | 37 +++++++++++++++++++++++++++++++++++++ src/utils.rs | 31 +++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/main.rs create mode 100644 src/utils.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..27aff38 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +*.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..12b867c --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "tlsa" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +inotify = "0.10" +hyper = { version = "0.14", features = ["full"] } +tokio = { version = "1", features = ["full"] } +tokio-test = "0.4.2" +hyper-tls = "0.5.0" +cookie = "0.15.1" +serde = { version = "1", features = ["derive"] } +serde_json = "1" +sha1 = { version = "0.6", features = ["std"] } + diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..4db09ad --- /dev/null +++ b/src/main.rs @@ -0,0 +1,37 @@ +use std::time::{UNIX_EPOCH, SystemTime}; +use hyper_tls::HttpsConnector; +use hyper::{Client, Method}; +use serde_json::json; +use crate::utils::{body_to_str, build_request}; + +mod utils; + +#[tokio::main] +async fn main() { + let client = Client::builder().build::<_, hyper::Body>(HttpsConnector::new()); + let application_key = ""; + let application_secret = ""; + let consumer_key = ""; + + let req = build_request(application_key, application_secret, consumer_key, + &Method::GET, "https://eu.api.ovh.com/1.0/auth/time", "", 0); + let res = client.request(req).await.unwrap(); + let s = res.status(); + assert!(s.is_success()); + let b = body_to_str(res.into_body()).await.parse::().unwrap(); + let delta = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() as i64 - b; + println!("Delta is {}", delta); + + let req = build_request(application_key, application_secret, consumer_key, + &Method::GET, "https://eu.api.ovh.com/1.0/domain/zone/{zone}/", "", delta); + let res = client.request(req).await.unwrap(); + println!("{} - {}", res.status(), body_to_str(res.into_body()).await); + + + let req = build_request(application_key, application_secret, consumer_key, + &Method::POST, "https://eu.api.ovh.com/1.0/domain/zone/{zone}/record", + &json!({"fieldType" : "TXT", "subDomain": "XXXXXX", "target": "XXXXXXXXXXXXXXX"}).to_string(), delta); + let res = client.request(req).await.unwrap(); + println!("{} - {}", res.status(), body_to_str(res.into_body()).await); +} + diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..8ab23d3 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,31 @@ +use std::time::{UNIX_EPOCH, SystemTime}; +use hyper::{Request, Method, Body, body}; + +pub async fn body_to_str(res: Body) -> String { + return String::from_utf8(body::to_bytes(res).await.unwrap().to_vec()).unwrap(); +} + +pub fn get_signature(app_secret: &str, consumer_key: &str, method: &Method, + query: &str, body: &str, delta: i64) -> String { + let stringapi = format!("{}+{}+{}+{}+{}+{}", app_secret, consumer_key, + method.as_str(), query, body, + SystemTime::now().duration_since(UNIX_EPOCH) + .unwrap().as_secs() as i64 + delta); + return format!("$1${}", sha1::Sha1::from(stringapi).hexdigest()); +} + +pub fn build_request(app_key: &str, app_secret: &str, consumer_key: &str, + method: &Method, uri: &str, body: &str, delta: i64) -> Request { + return Request::builder() + .method(method) + .uri(uri) + .header("X-Ovh-Application", app_key) + .header("X-Ovh-Timestamp", SystemTime::now().duration_since(UNIX_EPOCH) + .unwrap().as_secs() as i64 + delta) + .header("X-Ovh-Consumer", consumer_key) + .header("X-Ovh-Signature", get_signature(app_secret, consumer_key, method, + uri, body, delta)) + .header("Content-Type", "application/json;charset=utf-8") + .body(Body::from(body.to_string())) + .expect("Build"); +}