From: "Fabian Grünbichler" <f.gruenbichler@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [RFC proxmox-backup 11/15] client: allow using ApiToken + secret
Date: Mon, 19 Oct 2020 09:39:15 +0200 [thread overview]
Message-ID: <20201019073919.588521-12-f.gruenbichler@proxmox.com> (raw)
In-Reply-To: <20201019073919.588521-1-f.gruenbichler@proxmox.com>
in place of user + password.
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
Notes:
this will need a followup to disentangle user+password/tokenid+secret and host+port from the datastore
src/api2/types/mod.rs | 2 +-
src/client/http_client.rs | 41 +++++++++++++++++++++++++++++----------
2 files changed, 32 insertions(+), 11 deletions(-)
diff --git a/src/api2/types/mod.rs b/src/api2/types/mod.rs
index 65411f73..67740ca8 100644
--- a/src/api2/types/mod.rs
+++ b/src/api2/types/mod.rs
@@ -66,7 +66,7 @@ const_regex!{
pub DNS_NAME_OR_IP_REGEX = concat!(r"^(?:", DNS_NAME!(), "|", IPRE!(), r")$");
- pub BACKUP_REPO_URL_REGEX = concat!(r"^^(?:(?:(", USER_ID_REGEX_STR!(), ")@)?(", DNS_NAME!(), "|", IPRE_BRACKET!() ,"):)?(?:([0-9]{1,5}):)?(", PROXMOX_SAFE_ID_REGEX_STR!(), r")$");
+ pub BACKUP_REPO_URL_REGEX = concat!(r"^^(?:(?:(", USER_ID_REGEX_STR!(), "|", APITOKEN_ID_REGEX_STR!(), ")@)?(", DNS_NAME!(), "|", IPRE_BRACKET!() ,"):)?(?:([0-9]{1,5}):)?(", PROXMOX_SAFE_ID_REGEX_STR!(), r")$");
pub CERT_FINGERPRINT_SHA256_REGEX = r"^(?:[0-9a-fA-F][0-9a-fA-F])(?::[0-9a-fA-F][0-9a-fA-F]){31}$";
diff --git a/src/client/http_client.rs b/src/client/http_client.rs
index f0f6b9ce..8881d9a0 100644
--- a/src/client/http_client.rs
+++ b/src/client/http_client.rs
@@ -101,7 +101,7 @@ pub struct HttpClient {
server: String,
port: u16,
fingerprint: Arc<Mutex<Option<String>>>,
- first_auth: BroadcastFuture<()>,
+ first_auth: Option<BroadcastFuture<()>>,
auth: Arc<RwLock<AuthInfo>>,
ticket_abort: futures::future::AbortHandle,
_options: HttpClientOptions,
@@ -375,6 +375,13 @@ impl HttpClient {
}
});
+ let first_auth = if userid.is_tokenid() {
+ // TODO check access here?
+ None
+ } else {
+ Some(BroadcastFuture::new(Box::new(login_future)))
+ };
+
Ok(Self {
client,
server: String::from(server),
@@ -382,7 +389,7 @@ impl HttpClient {
fingerprint: verified_fingerprint,
auth,
ticket_abort,
- first_auth: BroadcastFuture::new(Box::new(login_future)),
+ first_auth,
_options: options,
})
}
@@ -392,7 +399,10 @@ impl HttpClient {
/// Login is done on demand, so this is only required if you need
/// access to authentication data in 'AuthInfo'.
pub async fn login(&self) -> Result<AuthInfo, Error> {
- self.first_auth.listen().await?;
+ if let Some(future) = &self.first_auth {
+ future.listen().await?;
+ }
+
let authinfo = self.auth.read().unwrap();
Ok(authinfo.clone())
}
@@ -475,10 +485,14 @@ impl HttpClient {
let client = self.client.clone();
let auth = self.login().await?;
-
- let enc_ticket = format!("PBSAuthCookie={}", percent_encode(auth.ticket.as_bytes(), DEFAULT_ENCODE_SET));
- req.headers_mut().insert("Cookie", HeaderValue::from_str(&enc_ticket).unwrap());
- req.headers_mut().insert("CSRFPreventionToken", HeaderValue::from_str(&auth.token).unwrap());
+ if auth.userid.is_tokenid() {
+ let enc_api_token = format!("{}:{}", auth.userid, percent_encode(auth.ticket.as_bytes(), DEFAULT_ENCODE_SET));
+ req.headers_mut().insert("Authorization", HeaderValue::from_str(&enc_api_token).unwrap());
+ } else {
+ let enc_ticket = format!("PBSAuthCookie={}", percent_encode(auth.ticket.as_bytes(), DEFAULT_ENCODE_SET));
+ req.headers_mut().insert("Cookie", HeaderValue::from_str(&enc_ticket).unwrap());
+ req.headers_mut().insert("CSRFPreventionToken", HeaderValue::from_str(&auth.token).unwrap());
+ }
Self::api_request(client, req).await
}
@@ -577,11 +591,18 @@ impl HttpClient {
protocol_name: String,
) -> Result<(H2Client, futures::future::AbortHandle), Error> {
- let auth = self.login().await?;
let client = self.client.clone();
+ let auth = self.login().await?;
+
+ if auth.userid.is_tokenid() {
+ let enc_api_token = format!("{}:{}", auth.userid, percent_encode(auth.ticket.as_bytes(), DEFAULT_ENCODE_SET));
+ req.headers_mut().insert("Authorization", HeaderValue::from_str(&enc_api_token).unwrap());
+ } else {
+ let enc_ticket = format!("PBSAuthCookie={}", percent_encode(auth.ticket.as_bytes(), DEFAULT_ENCODE_SET));
+ req.headers_mut().insert("Cookie", HeaderValue::from_str(&enc_ticket).unwrap());
+ req.headers_mut().insert("CSRFPreventionToken", HeaderValue::from_str(&auth.token).unwrap());
+ }
- let enc_ticket = format!("PBSAuthCookie={}", percent_encode(auth.ticket.as_bytes(), DEFAULT_ENCODE_SET));
- req.headers_mut().insert("Cookie", HeaderValue::from_str(&enc_ticket).unwrap());
req.headers_mut().insert("UPGRADE", HeaderValue::from_str(&protocol_name).unwrap());
let resp = client.request(req).await?;
--
2.20.1
next prev parent reply other threads:[~2020-10-19 7:40 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-19 7:39 [pbs-devel] [RFC proxmox-backup 00/15] API tokens Fabian Grünbichler
2020-10-19 7:39 ` [pbs-devel] [PATCH proxmox-backup 01/15] fix indentation Fabian Grünbichler
2020-10-19 12:00 ` [pbs-devel] applied: " Thomas Lamprecht
2020-10-19 7:39 ` [pbs-devel] [PATCH proxmox-backup 02/15] fix typos Fabian Grünbichler
2020-10-19 12:01 ` [pbs-devel] applied: " Thomas Lamprecht
2020-10-19 7:39 ` [pbs-devel] [PATCH proxmox-backup 03/15] REST: rename token to csrf_token Fabian Grünbichler
2020-10-19 12:02 ` [pbs-devel] applied: " Thomas Lamprecht
2020-10-19 7:39 ` [pbs-devel] [RFC proxmox-backup 04/15] Userid: extend schema with token name Fabian Grünbichler
2020-10-19 7:39 ` [pbs-devel] [RFC proxmox-backup 05/15] add ApiToken to user.cfg and CachedUserInfo Fabian Grünbichler
2020-10-19 7:39 ` [pbs-devel] [RFC proxmox-backup 06/15] config: add token.shadow file Fabian Grünbichler
2020-10-19 7:39 ` [pbs-devel] [RFC proxmox-backup 07/15] REST: extract and handle API tokens Fabian Grünbichler
2020-10-20 8:34 ` Wolfgang Bumiller
2020-10-19 7:39 ` [pbs-devel] [RFC proxmox-backup 08/15] api: add API token endpoints Fabian Grünbichler
2020-10-20 9:42 ` Wolfgang Bumiller
2020-10-20 10:15 ` Wolfgang Bumiller
2020-10-19 7:39 ` [pbs-devel] [RFC proxmox-backup 09/15] api: allow listing users + tokens Fabian Grünbichler
2020-10-20 10:10 ` Wolfgang Bumiller
2020-10-19 7:39 ` [pbs-devel] [RFC proxmox-backup 10/15] api: add permissions endpoint Fabian Grünbichler
2020-10-19 7:39 ` Fabian Grünbichler [this message]
2020-10-19 7:39 ` [pbs-devel] [RFC proxmox-backup 12/15] owner checks: handle backups owned by API tokens Fabian Grünbichler
2020-10-19 7:39 ` [pbs-devel] [RFC proxmox-backup 13/15] tasks: allow unpriv users to read their tokens' tasks Fabian Grünbichler
2020-10-19 7:39 ` [pbs-devel] [RFC proxmox-backup 14/15] manager: add token commands Fabian Grünbichler
2020-10-19 7:39 ` [pbs-devel] [RFC proxmox-backup 15/15] manager: add user permissions command Fabian Grünbichler
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20201019073919.588521-12-f.gruenbichler@proxmox.com \
--to=f.gruenbichler@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox