Improve use of github token (#1769)

* Add new dep zeroize

* Use Zeroizing to avoid leaking the token

* Optimize gh-auth-token

Spawn it as a task, and only await it
when using GhApiClient

* Fix binstalk-git-repo-api unit tests
This commit is contained in:
Jiahao XU 2024-06-15 15:42:09 +10:00 committed by GitHub
parent e3c8c40806
commit fff6aa8122
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 128 additions and 54 deletions

View file

@ -43,6 +43,7 @@ tokio = { version = "1.35.0", features = [
], default-features = false }
tracing = "0.1.39"
url = { version = "2.3.1", features = ["serde"] }
zeroize = "1.8.1"
[features]
default = ["static", "rustls", "git"]

View file

@ -3,6 +3,7 @@ pub mod remote {
pub use binstalk_downloader::remote::*;
pub use url::ParseError as UrlParseError;
}
pub mod lazy_gh_api_client;
pub(crate) mod target_triple;
pub mod tasks;

View file

@ -0,0 +1,53 @@
use std::{future::Future, sync::Mutex};
use binstalk_git_repo_api::gh_api_client::GhApiClient;
use tokio::sync::OnceCell;
use zeroize::Zeroizing;
use crate::{
errors::BinstallError,
helpers::{remote, tasks::AutoAbortJoinHandle},
};
pub type GitHubToken = Option<Zeroizing<Box<str>>>;
#[derive(Debug)]
pub struct LazyGhApiClient {
client: remote::Client,
inner: OnceCell<GhApiClient>,
task: Mutex<Option<AutoAbortJoinHandle<GitHubToken>>>,
}
impl LazyGhApiClient {
pub fn new(client: remote::Client, auth_token: GitHubToken) -> Self {
Self {
inner: OnceCell::new_with(Some(GhApiClient::new(client.clone(), auth_token))),
client,
task: Mutex::new(None),
}
}
pub fn with_get_gh_token_future<Fut>(client: remote::Client, get_auth_token_future: Fut) -> Self
where
Fut: Future<Output = GitHubToken> + Send + Sync + 'static,
{
Self {
inner: OnceCell::new(),
task: Mutex::new(Some(AutoAbortJoinHandle::spawn(get_auth_token_future))),
client,
}
}
pub async fn get(&self) -> Result<&GhApiClient, BinstallError> {
self.inner
.get_or_try_init(|| async {
let task = self.task.lock().unwrap().take();
Ok(if let Some(task) = task {
GhApiClient::new(self.client.clone(), task.await?)
} else {
GhApiClient::new(self.client.clone(), None)
})
})
.await
}
}

View file

@ -6,7 +6,10 @@ use semver::VersionReq;
use crate::{
fetchers::{Data, Fetcher, SignaturePolicy, TargetDataErased},
helpers::{gh_api_client::GhApiClient, jobserver_client::LazyJobserverClient, remote::Client},
helpers::{
gh_api_client::GhApiClient, jobserver_client::LazyJobserverClient,
lazy_gh_api_client::LazyGhApiClient, remote::Client,
},
manifests::cargo_toml_binstall::PkgOverride,
registry::Registry,
DesiredTargets,
@ -47,7 +50,7 @@ pub struct Options {
pub cargo_root: Option<PathBuf>,
pub client: Client,
pub gh_api_client: GhApiClient,
pub gh_api_client: LazyGhApiClient,
pub jobserver_client: LazyJobserverClient,
pub registry: Registry,

View file

@ -106,6 +106,8 @@ async fn resolve_inner(
},
);
let gh_api_client = opts.gh_api_client.get().await?;
let mut handles_fn =
|data: Arc<Data>, filter_fetcher_by_name_predicate: fn(&'static str) -> bool| {
handles.extend(
@ -132,7 +134,7 @@ async fn resolve_inner(
.filter_map(|(f, target_data)| {
let fetcher = f(
opts.client.clone(),
opts.gh_api_client.clone(),
gh_api_client.clone(),
data.clone(),
target_data,
opts.signature_policy,