]> git.proxmox.com Git - proxmox-backup.git/commitdiff
src/client/http_client.rs: try to login
authorDietmar Maurer <dietmar@proxmox.com>
Wed, 13 Feb 2019 13:31:43 +0000 (14:31 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Wed, 13 Feb 2019 13:31:43 +0000 (14:31 +0100)
use an environment var to store passphrase (PBS_PASSWORD)

src/bin/proxmox-backup-client.rs
src/client/http_client.rs
src/server/rest.rs

index 962805b943b8cad81be38f92b273ac3baa12fec5..8bbaa0f07949c66c29b0552b30738cd2b6f79963 100644 (file)
@@ -53,7 +53,7 @@ impl BackupRepository {
 
 fn backup_directory(repo: &BackupRepository, body: Body, archive_name: &str) -> Result<(), Error> {
 
-    let client = HttpClient::new(&repo.host);
+    let client = HttpClient::new(&repo.host, &repo.user);
 
     let epoch = std::time::SystemTime::now().duration_since(
         std::time::SystemTime::UNIX_EPOCH)?.as_secs();
@@ -107,7 +107,7 @@ fn list_backups(
     let repo_url = tools::required_string_param(&param, "repository")?;
     let repo = BackupRepository::parse(repo_url)?;
 
-    let client = HttpClient::new(&repo.host);
+    let client = HttpClient::new(&repo.host, &repo.user);
 
     let path = format!("api2/json/admin/datastore/{}/backups", repo.store);
 
index d90407e423d0d5e32d589d4da7bf9617c4f8faa5..3b76b4549685ba5fa14902bc0400e079554b106c 100644 (file)
@@ -9,16 +9,19 @@ use http::Request;
 use futures::stream::Stream;
 
 use serde_json::{Value};
+use url::percent_encoding::{percent_encode,  DEFAULT_ENCODE_SET};
 
 pub struct HttpClient {
+    username: String,
     server: String,
 }
 
 impl HttpClient {
 
-    pub fn new(server: &str) -> Self {
+    pub fn new(server: &str, username: &str) -> Self {
         Self {
             server: String::from(server),
+            username: String::from(username),
         }
     }
 
@@ -77,23 +80,64 @@ impl HttpClient {
 
         let url: Uri = format!("https://{}:8007/{}", self.server, path).parse()?;
 
+        let ticket = self.login()?;
+
+        let enc_ticket = percent_encode(ticket.as_bytes(), DEFAULT_ENCODE_SET).to_string();
+
         let request = Request::builder()
             .method("GET")
             .uri(url)
             .header("User-Agent", "proxmox-backup-client/1.0")
+            .header("Cookie", format!("PBSAuthCookie={}", enc_ticket))
             .body(Body::empty())?;
 
         Self::run_request(request)
     }
 
+    fn login(&self) ->  Result<String, Error> {
+
+        let url: Uri = format!("https://{}:8007/{}", self.server, "/api2/json/access/ticket").parse()?;
+
+        let password = match std::env::var("PBS_PASSWORD") {
+            Ok(p) => p,
+            Err(err) => bail!("missing passphrase - {}", err),
+        };
+
+        let query = url::form_urlencoded::Serializer::new(String::new())
+            .append_pair("username", &self.username)
+            .append_pair("password", &password)
+            .finish();
+
+        let request = Request::builder()
+            .method("POST")
+            .uri(url)
+            .header("User-Agent", "proxmox-backup-client/1.0")
+            .header("Content-Type", "application/x-www-form-urlencoded")
+            .body(Body::from(query))?;
+
+        let auth_res = Self::run_request(request)?;
+
+        let ticket = match auth_res["data"]["ticket"].as_str() {
+            Some(t) => t,
+            None => bail!("got unexpected respose for login request."),
+        };
+
+        Ok(ticket.to_owned())
+    }
+
     pub fn upload(&self, content_type: &str, body: Body, path: &str) -> Result<Value, Error> {
 
         let url: Uri = format!("https://{}:8007/{}", self.server, path).parse()?;
 
+        let ticket = self.login()?;
+
+        let enc_ticket = percent_encode(ticket.as_bytes(), DEFAULT_ENCODE_SET).to_string();
+
         let request = Request::builder()
             .method("POST")
             .uri(url)
             .header("User-Agent", "proxmox-backup-client/1.0")
+            .header("Cookie", format!("PBSAuthCookie={}", enc_ticket))
             .header("Content-Type", content_type)
             .body(body)?;
 
index 1c63c3e9ee5ff85bd7a0c70531f8f35527a7ae74..49e4a8b46cd121bac162041b948db92ca72b17a2 100644 (file)
@@ -70,7 +70,7 @@ impl Service for ApiService {
             match result {
                 Ok(res) => Ok::<_, hyper::Error>(res),
                 Err(err) => {
-                     if let Some(apierr) = err.downcast_ref::<HttpError>() {
+                    if let Some(apierr) = err.downcast_ref::<HttpError>() {
                         let mut resp = Response::new(Body::from(apierr.message.clone()));
                         *resp.status_mut() = apierr.code;
                         Ok(resp)
@@ -458,6 +458,8 @@ pub fn handle_request(api: Arc<ApiConfig>, req: Request<Body>) -> BoxFut {
                 if let Some(_username) = rpcenv.get_user() {
                     // fixme: check permissions
                 } else {
+                    println!("Abort UNAUTHORIZED API REQUEST");
+
                     // always delay unauthorized calls by 3 seconds (from start of request)
                     let resp = (formatter.format_error)(http_err!(UNAUTHORIZED, "permission check failed.".into()));
                     let delayed_response = tokio::timer::Delay::new(delay_unauth_time)