Remove use of /cache/token to get a fallback cache

We rely on the GitHub token creating a project on FlakeHub as a side
effect.
This commit is contained in:
Eelco Dolstra 2024-01-10 21:31:14 +01:00
parent 0d9e0c088c
commit 0d5e889783
4 changed files with 26 additions and 133 deletions

46
Cargo.lock generated
View file

@ -137,7 +137,7 @@ version = "0.2.0"
source = "git+ssh://git@github.com/DeterminateSystems/attic-priv?branch=main#a16c0f4cf1abe471ac69731bf3cfe9a8d2eedd5e"
dependencies = [
"async-stream",
"base64 0.21.2",
"base64",
"bytes",
"cxx",
"cxx-build",
@ -255,12 +255,6 @@ dependencies = [
"syn 2.0.32",
]
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
version = "0.21.2"
@ -623,7 +617,6 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]]
@ -930,15 +923,6 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]]
name = "hostname"
version = "0.3.1"
@ -1209,21 +1193,6 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "jwt"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6204285f77fe7d9784db3fdc449ecce1a0114927a51d5a41c4c7a292011c015f"
dependencies = [
"base64 0.13.1",
"crypto-common",
"digest",
"hmac",
"serde",
"serde_json",
"sha2",
]
[[package]]
name = "kqueue"
version = "1.0.8"
@ -1322,7 +1291,6 @@ dependencies = [
"gha-cache",
"indicatif",
"is_ci",
"jwt",
"netrc-rs",
"reqwest",
"serde",
@ -1666,7 +1634,7 @@ version = "0.11.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55"
dependencies = [
"base64 0.21.2",
"base64",
"bytes",
"encoding_rs",
"futures-core",
@ -1799,7 +1767,7 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
dependencies = [
"base64 0.21.2",
"base64",
]
[[package]]
@ -1954,7 +1922,7 @@ version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23"
dependencies = [
"base64 0.21.2",
"base64",
"chrono",
"hex",
"indexmap 1.9.3",
@ -2065,12 +2033,6 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "subtle"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
version = "1.0.109"

View file

@ -23,7 +23,6 @@ is_ci = "1.1.1"
sha2 = { version = "0.10.6", default-features = false }
reqwest = { version = "0.11.17", default-features = false, features = ["blocking", "rustls-tls-native-roots", "trust-dns"] }
netrc-rs = "0.1.2"
jwt = { version = "0.16" }
attic = { git = "ssh://git@github.com/DeterminateSystems/attic-priv", branch = "main" }
#attic = { path = "../../attic-priv/attic" }
attic-client = { git = "ssh://git@github.com/DeterminateSystems/attic-priv", branch = "main" }

View file

@ -34,8 +34,8 @@ pub enum Error {
#[error("FlakeHub HTTP error: {0}")]
FlakeHubHttp(#[from] reqwest::Error),
#[error("Got HTTP response {1} getting FlakeHub binary cache creation token from {0}: {2}")]
CacheCreation(reqwest::Url, reqwest::StatusCode, String),
#[error("Got HTTP response {0} getting the cache name from FlakeHub: {1}")]
GetCacheName(reqwest::StatusCode, String),
#[error("netrc parse error: {0}")]
Netrc(netrc_rs::Error),
@ -43,20 +43,11 @@ pub enum Error {
#[error("Cannot find netrc credentials for {0}")]
MissingCreds(String),
#[error("Received bad JWT")]
BadJWT,
#[error("Received bad JWT token: {0}")]
JWTParsing(#[from] jwt::Error),
#[error("Attic error: {0}")]
Attic(#[from] attic::AtticError),
#[error("Bad URL")]
BadURL(reqwest::Url),
#[error("FlakeHub did not return any cache for the calling user")]
NoKnownCaches,
}
impl IntoResponse for Error {

View file

@ -18,7 +18,6 @@ use tokio::fs::File;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use uuid::Uuid;
const JWT_PREFIX: &str = "flakehub1_";
const USER_AGENT: &str = "magic-nix-cache";
pub struct State {
@ -99,87 +98,29 @@ pub async fn init_cache(
.send()
.await?;
if response.status().is_success() {
#[derive(Deserialize)]
struct ProjectInfo {
organization_uuid_v7: Uuid,
project_uuid_v7: Uuid,
}
let project_info = response.json::<ProjectInfo>().await?;
let cache_name = format!(
"{}:{}",
project_info.organization_uuid_v7, project_info.project_uuid_v7,
);
tracing::info!("Using cache {:?}.", cache_name);
cache_name
} else {
tracing::error!(
"Failed to get project info from {}: {}",
url,
response.status()
);
// As a fallback (if the project doesn't exist yet on
// FlakeHub), get the list of known caches for this user
// and use the oldest one. FIXME: this might not be a good
// idea.
// FIXME: we don't actually need this token. We just need
// to query the caches the user has access to.
let url = flakehub_api_server.join("cache/token").unwrap();
let request = reqwest::Client::new()
.post(url.to_owned())
.header("User-Agent", USER_AGENT)
.basic_auth(
netrc_entry.login.as_ref().unwrap(),
netrc_entry.password.as_ref(),
);
let response = request.send().await?;
if !response.status().is_success() {
return Err(Error::CacheCreation(
url,
response.status(),
response.text().await?,
));
}
#[derive(Deserialize)]
struct Response {
token: String,
}
let token = response.json::<Response>().await?.token;
// Parse the JWT to get the list of caches to which we have access.
let jwt = token.strip_prefix(JWT_PREFIX).ok_or(Error::BadJWT)?;
let jwt_parsed: jwt::Token<jwt::Header, serde_json::Map<String, serde_json::Value>, _> =
jwt::Token::parse_unverified(jwt)?;
let known_caches = jwt_parsed
.claims()
.get("https://cache.flakehub.com/v1")
.ok_or(Error::BadJWT)?
.get("caches")
.ok_or(Error::BadJWT)?
.as_object()
.ok_or(Error::BadJWT)?;
let mut keys: Vec<_> = known_caches.keys().collect();
keys.sort();
let cache_name = keys.first().ok_or(Error::NoKnownCaches)?.to_string();
tracing::info!("Falling back to existing cache {}.", cache_name);
cache_name
if !response.status().is_success() {
return Err(Error::GetCacheName(
response.status(),
response.text().await?,
));
}
#[derive(Deserialize)]
struct ProjectInfo {
organization_uuid_v7: Uuid,
project_uuid_v7: Uuid,
}
let project_info = response.json::<ProjectInfo>().await?;
format!(
"{}:{}",
project_info.organization_uuid_v7, project_info.project_uuid_v7,
)
};
tracing::info!("Using cache {:?}.", cache_name);
let cache = CacheSliceIdentifier::from_str(&cache_name)?;
// Create the cache.