aboutsummaryrefslogtreecommitdiffstats
path: root/rs
diff options
context:
space:
mode:
authorLibravatar Rutger Broekhoff2024-01-19 15:45:48 +0100
committerLibravatar Rutger Broekhoff2024-01-19 15:45:48 +0100
commitefe9d55ea6c01c718d3c53dbcee6b48899b48267 (patch)
tree97ff392c814290f12023e9c581078f9a10c4174c /rs
parent0956476fda305f48644e53305e12ae46cb67a32b (diff)
downloadgitolfs3-efe9d55ea6c01c718d3c53dbcee6b48899b48267.tar.gz
gitolfs3-efe9d55ea6c01c718d3c53dbcee6b48899b48267.zip
Implement downloading objects for trusted forwarded hosts
Diffstat (limited to 'rs')
-rw-r--r--rs/server/src/main.rs37
1 files changed, 29 insertions, 8 deletions
diff --git a/rs/server/src/main.rs b/rs/server/src/main.rs
index aebeb88..0266f61 100644
--- a/rs/server/src/main.rs
+++ b/rs/server/src/main.rs
@@ -299,7 +299,7 @@ struct BatchResponseObjectAction {
299 expires_at: DateTime<Utc>, 299 expires_at: DateTime<Utc>,
300} 300}
301 301
302#[derive(Debug, Serialize, Clone)] 302#[derive(Default, Debug, Serialize, Clone)]
303struct BatchResponseObjectActions { 303struct BatchResponseObjectActions {
304 #[serde(skip_serializing_if = "Option::is_none")] 304 #[serde(skip_serializing_if = "Option::is_none")]
305 upload: Option<BatchResponseObjectAction>, 305 upload: Option<BatchResponseObjectAction>,
@@ -315,6 +315,7 @@ struct BatchResponseObject {
315 size: i64, 315 size: i64,
316 #[serde(skip_serializing_if = "Option::is_none")] 316 #[serde(skip_serializing_if = "Option::is_none")]
317 authenticated: Option<bool>, 317 authenticated: Option<bool>,
318 actions: BatchResponseObjectActions,
318} 319}
319 320
320#[derive(Debug, Serialize, Clone)] 321#[derive(Debug, Serialize, Clone)]
@@ -342,7 +343,7 @@ fn validate_size(expected: i64, obj: &HeadObjectOutput) -> bool {
342 true 343 true
343} 344}
344 345
345async fn handle_download_object(state: &AppState, repo: &str, obj: &BatchRequestObject) { 346async fn handle_download_object(state: &AppState, repo: &str, obj: &BatchRequestObject, trusted: bool) -> BatchResponseObject {
346 let (oid0, oid1) = (HexByte(obj.oid[0]), HexByte(obj.oid[1])); 347 let (oid0, oid1) = (HexByte(obj.oid[0]), HexByte(obj.oid[1]));
347 let full_path = format!("{repo}/lfs/objects/{}/{}/{}", oid0, oid1, obj.oid); 348 let full_path = format!("{repo}/lfs/objects/{}/{}/{}", oid0, oid1, obj.oid);
348 349
@@ -354,16 +355,36 @@ async fn handle_download_object(state: &AppState, repo: &str, obj: &BatchRequest
354 .checksum_mode(aws_sdk_s3::types::ChecksumMode::Enabled) 355 .checksum_mode(aws_sdk_s3::types::ChecksumMode::Enabled)
355 .send() 356 .send()
356 .await 357 .await
357 .unwrap(); 358 .unwrap(); // TODO: don't unwrap()
358 // Scaleway actually doesn't provide SHA256 suport, but maybe in the future :) 359 // Scaleway actually doesn't provide SHA256 suport, but maybe in the future :)
359 if !validate_checksum(obj.oid, &result) { 360 if !validate_checksum(obj.oid, &result) {
360 unreachable!(); 361 todo!();
361 } 362 }
362 if !validate_size(obj.size, &result) { 363 if !validate_size(obj.size, &result) {
363 unreachable!(); 364 todo!();
364 } 365 }
365 366
366 let expires_at = Utc::now() + Duration::seconds(5 * 60); 367 let expires_in = std::time::Duration::from_secs(5 * 60);
368 let expires_at = Utc::now() + expires_in;
369
370 if trusted {
371 let config = aws_sdk_s3::presigning::PresigningConfig::expires_in(expires_in).unwrap();
372 let presigned = state.s3_client.get_object().presigned(config).await.unwrap();
373 return BatchResponseObject{
374 oid: obj.oid,
375 size: obj.size,
376 authenticated: Some(true),
377 actions: BatchResponseObjectActions {
378 download: Some(BatchResponseObjectAction{
379 header: presigned.headers().map(|(k, v)| (k.to_owned(), v.to_owned())).collect(),
380 expires_at,
381 href: presigned.uri().to_string(),
382 }),
383 ..Default::default()
384 }
385 };
386 }
387 todo!();
367} 388}
368 389
369struct AuthorizationConfig { 390struct AuthorizationConfig {
@@ -496,7 +517,7 @@ async fn batch(
496 let Some(public) = is_repo_public(&repo) else { 517 let Some(public) = is_repo_public(&repo) else {
497 return REPO_NOT_FOUND.into_response(); 518 return REPO_NOT_FOUND.into_response();
498 }; 519 };
499 let authn = match authorize( 520 let Trusted(trusted) = match authorize(
500 &state.authz_conf, 521 &state.authz_conf,
501 &headers, 522 &headers,
502 &repo, 523 &repo,
@@ -528,7 +549,7 @@ async fn batch(
528 549
529 let resp: BatchResponse; 550 let resp: BatchResponse;
530 for obj in payload.objects { 551 for obj in payload.objects {
531 handle_download_object(&state, &repo, &obj).await; 552 handle_download_object(&state, &repo, &obj, trusted).await;
532 // match payload.operation { 553 // match payload.operation {
533 // Operation::Download => resp.objects.push(handle_download_object(repo, obj));, 554 // Operation::Download => resp.objects.push(handle_download_object(repo, obj));,
534 // Operation::Upload => resp.objects.push(handle_upload_object(repo, obj)), 555 // Operation::Upload => resp.objects.push(handle_upload_object(repo, obj)),