diff options
| author | Rutger Broekhoff | 2024-04-29 19:18:56 +0200 |
|---|---|---|
| committer | Rutger Broekhoff | 2024-04-29 19:18:56 +0200 |
| commit | a7f9c8de31231b9fd9c67c57db659f7b01f1a3b0 (patch) | |
| tree | 040c518d243769c1920b8201a07a626f4e5934cf | |
| parent | 80c4d49ad7f590f5af1304939fdaea7baf13142e (diff) | |
| download | gitolfs3-a7f9c8de31231b9fd9c67c57db659f7b01f1a3b0.tar.gz gitolfs3-a7f9c8de31231b9fd9c67c57db659f7b01f1a3b0.zip | |
Rename crates (and therefore commands)
| -rw-r--r-- | Cargo.lock | 70 | ||||
| -rw-r--r-- | Cargo.toml | 8 | ||||
| -rw-r--r-- | docs/man/gitolfs3-authenticate.1 | 4 | ||||
| -rw-r--r-- | docs/man/gitolfs3-server.1 | 4 | ||||
| -rw-r--r-- | docs/man/gitolfs3-shell.1 | 4 | ||||
| -rw-r--r-- | gitolfs3-authenticate/Cargo.toml (renamed from git-lfs-authenticate/Cargo.toml) | 4 | ||||
| -rw-r--r-- | gitolfs3-authenticate/src/main.rs (renamed from git-lfs-authenticate/src/main.rs) | 15 | ||||
| -rw-r--r-- | gitolfs3-common/Cargo.toml (renamed from common/Cargo.toml) | 2 | ||||
| -rw-r--r-- | gitolfs3-common/src/lib.rs (renamed from common/src/lib.rs) | 0 | ||||
| -rw-r--r-- | gitolfs3-server/Cargo.toml (renamed from server/Cargo.toml) | 4 | ||||
| -rw-r--r-- | gitolfs3-server/src/main.rs (renamed from server/src/main.rs) | 77 | ||||
| -rw-r--r-- | gitolfs3-shell/Cargo.toml (renamed from shell/Cargo.toml) | 2 | ||||
| -rw-r--r-- | gitolfs3-shell/src/main.rs (renamed from shell/src/main.rs) | 2 |
13 files changed, 101 insertions, 95 deletions
| @@ -625,16 +625,6 @@ dependencies = [ | |||
| 625 | ] | 625 | ] |
| 626 | 626 | ||
| 627 | [[package]] | 627 | [[package]] |
| 628 | name = "common" | ||
| 629 | version = "0.1.0" | ||
| 630 | dependencies = [ | ||
| 631 | "chrono", | ||
| 632 | "hmac-sha256", | ||
| 633 | "serde", | ||
| 634 | "subtle", | ||
| 635 | ] | ||
| 636 | |||
| 637 | [[package]] | ||
| 638 | name = "const-oid" | 628 | name = "const-oid" |
| 639 | version = "0.9.6" | 629 | version = "0.9.6" |
| 640 | source = "registry+https://github.com/rust-lang/crates.io-index" | 630 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -887,16 +877,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| 887 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" | 877 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" |
| 888 | 878 | ||
| 889 | [[package]] | 879 | [[package]] |
| 890 | name = "git-lfs-authenticate" | 880 | name = "gitolfs3-authenticate" |
| 891 | version = "0.1.0" | 881 | version = "0.1.0" |
| 892 | dependencies = [ | 882 | dependencies = [ |
| 893 | "anyhow", | 883 | "anyhow", |
| 894 | "chrono", | 884 | "chrono", |
| 895 | "common", | 885 | "gitolfs3-common", |
| 886 | "serde_json", | ||
| 887 | ] | ||
| 888 | |||
| 889 | [[package]] | ||
| 890 | name = "gitolfs3-common" | ||
| 891 | version = "0.1.0" | ||
| 892 | dependencies = [ | ||
| 893 | "chrono", | ||
| 894 | "hmac-sha256", | ||
| 895 | "serde", | ||
| 896 | "subtle", | ||
| 897 | ] | ||
| 898 | |||
| 899 | [[package]] | ||
| 900 | name = "gitolfs3-server" | ||
| 901 | version = "0.1.0" | ||
| 902 | dependencies = [ | ||
| 903 | "aws-config", | ||
| 904 | "aws-sdk-s3", | ||
| 905 | "axum", | ||
| 906 | "base64", | ||
| 907 | "chrono", | ||
| 908 | "gitolfs3-common", | ||
| 909 | "mime", | ||
| 910 | "serde", | ||
| 896 | "serde_json", | 911 | "serde_json", |
| 912 | "tokio", | ||
| 913 | "tokio-util", | ||
| 914 | "tower", | ||
| 915 | "tracing-subscriber", | ||
| 897 | ] | 916 | ] |
| 898 | 917 | ||
| 899 | [[package]] | 918 | [[package]] |
| 919 | name = "gitolfs3-shell" | ||
| 920 | version = "0.1.0" | ||
| 921 | |||
| 922 | [[package]] | ||
| 900 | name = "group" | 923 | name = "group" |
| 901 | version = "0.12.1" | 924 | version = "0.12.1" |
| 902 | source = "registry+https://github.com/rust-lang/crates.io-index" | 925 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1727,25 +1750,6 @@ dependencies = [ | |||
| 1727 | ] | 1750 | ] |
| 1728 | 1751 | ||
| 1729 | [[package]] | 1752 | [[package]] |
| 1730 | name = "server" | ||
| 1731 | version = "0.1.0" | ||
| 1732 | dependencies = [ | ||
| 1733 | "aws-config", | ||
| 1734 | "aws-sdk-s3", | ||
| 1735 | "axum", | ||
| 1736 | "base64", | ||
| 1737 | "chrono", | ||
| 1738 | "common", | ||
| 1739 | "mime", | ||
| 1740 | "serde", | ||
| 1741 | "serde_json", | ||
| 1742 | "tokio", | ||
| 1743 | "tokio-util", | ||
| 1744 | "tower", | ||
| 1745 | "tracing-subscriber", | ||
| 1746 | ] | ||
| 1747 | |||
| 1748 | [[package]] | ||
| 1749 | name = "sha1" | 1753 | name = "sha1" |
| 1750 | version = "0.10.6" | 1754 | version = "0.10.6" |
| 1751 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1755 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1777,10 +1781,6 @@ dependencies = [ | |||
| 1777 | ] | 1781 | ] |
| 1778 | 1782 | ||
| 1779 | [[package]] | 1783 | [[package]] |
| 1780 | name = "shell" | ||
| 1781 | version = "0.1.0" | ||
| 1782 | |||
| 1783 | [[package]] | ||
| 1784 | name = "signal-hook-registry" | 1784 | name = "signal-hook-registry" |
| 1785 | version = "1.4.2" | 1785 | version = "1.4.2" |
| 1786 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1786 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| @@ -1,8 +1,8 @@ | |||
| 1 | [workspace] | 1 | [workspace] |
| 2 | resolver = "2" | 2 | resolver = "2" |
| 3 | members = [ | 3 | members = [ |
| 4 | "common", | 4 | "gitolfs3-common", |
| 5 | "git-lfs-authenticate", | 5 | "gitolfs3-authenticate", |
| 6 | "server", | 6 | "gitolfs3-server", |
| 7 | "shell", | 7 | "gitolfs3-shell", |
| 8 | ] | 8 | ] |
diff --git a/docs/man/gitolfs3-authenticate.1 b/docs/man/gitolfs3-authenticate.1 index 67151e1..38bf28f 100644 --- a/docs/man/gitolfs3-authenticate.1 +++ b/docs/man/gitolfs3-authenticate.1 | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | .TH GITOLFS3-AUTHENTICATE 1 2024-04-29 Gitolfs3 "Gitolfs3 Manual" | 1 | .TH GITOLFS3-AUTHENTICATE 1 2024-04-29 Gitolfs3 "Gitolfs3 Manual" |
| 2 | .SH NAME | 2 | .SH NAME |
| 3 | git-lfs-authenticate \- Git LFS authentication agent for Gitolfs3 | 3 | gitolfs3-authenticate \- Git LFS authentication agent for Gitolfs3 |
| 4 | .SH SYNOPSIS | 4 | .SH SYNOPSIS |
| 5 | .B git-lfs-authenticate | 5 | .B gitolfs3-authenticate |
| 6 | <repository> | 6 | <repository> |
| 7 | upload/download | 7 | upload/download |
| 8 | .SH DESCRIPTION | 8 | .SH DESCRIPTION |
diff --git a/docs/man/gitolfs3-server.1 b/docs/man/gitolfs3-server.1 index 4f384cf..f141bce 100644 --- a/docs/man/gitolfs3-server.1 +++ b/docs/man/gitolfs3-server.1 | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | .TH GITOLFS3-SERVER 1 2024-04-29 Gitolfs3 "Gitolfs3 Manual" | 1 | .TH GITOLFS3-SERVER 1 2024-04-29 Gitolfs3 "Gitolfs3 Manual" |
| 2 | .SH NAME | 2 | .SH NAME |
| 3 | server \- Gitolfs3 Git LFS server | 3 | gitolfs3-server \- Gitolfs3 Git LFS server |
| 4 | .SH SYNOPSIS | 4 | .SH SYNOPSIS |
| 5 | .B server | 5 | .B gitolfs3-server |
| 6 | .SH DESCRIPTION | 6 | .SH DESCRIPTION |
| 7 | .B server | 7 | .B server |
| 8 | is the Gitolfs3 Git LFS server. It is primarily configured using environment | 8 | is the Gitolfs3 Git LFS server. It is primarily configured using environment |
diff --git a/docs/man/gitolfs3-shell.1 b/docs/man/gitolfs3-shell.1 index 56eac31..a626682 100644 --- a/docs/man/gitolfs3-shell.1 +++ b/docs/man/gitolfs3-shell.1 | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | .TH GITOLFS3-SHELL 1 2024-04-29 Gitolfs3 "Gitolfs3 Manual" | 1 | .TH GITOLFS3-SHELL 1 2024-04-29 Gitolfs3 "Gitolfs3 Manual" |
| 2 | .SH NAME | 2 | .SH NAME |
| 3 | shell \- Gitolfs3 shell | 3 | gitolfs3-shell \- Gitolfs3 shell |
| 4 | .SH SYNOPSIS | 4 | .SH SYNOPSIS |
| 5 | .B shell | 5 | .B gitolfs3-shell |
| 6 | -c <command> | 6 | -c <command> |
| 7 | .SH DESCRIPTION | 7 | .SH DESCRIPTION |
| 8 | .B shell | 8 | .B shell |
diff --git a/git-lfs-authenticate/Cargo.toml b/gitolfs3-authenticate/Cargo.toml index 15feba8..5725abc 100644 --- a/git-lfs-authenticate/Cargo.toml +++ b/gitolfs3-authenticate/Cargo.toml | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | name = "git-lfs-authenticate" | 2 | name = "gitolfs3-authenticate" |
| 3 | version = "0.1.0" | 3 | version = "0.1.0" |
| 4 | edition = "2021" | 4 | edition = "2021" |
| 5 | 5 | ||
| 6 | [dependencies] | 6 | [dependencies] |
| 7 | anyhow = "1.0" | 7 | anyhow = "1.0" |
| 8 | chrono = "0.4" | 8 | chrono = "0.4" |
| 9 | common = { path = "../common" } | 9 | gitolfs3-common = { path = "../gitolfs3-common" } |
| 10 | serde_json = "1" | 10 | serde_json = "1" |
diff --git a/git-lfs-authenticate/src/main.rs b/gitolfs3-authenticate/src/main.rs index c9094a1..771f185 100644 --- a/git-lfs-authenticate/src/main.rs +++ b/gitolfs3-authenticate/src/main.rs | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | use anyhow::{anyhow, bail, Result}; | 1 | use anyhow::{anyhow, bail, Result}; |
| 2 | use chrono::Utc; | 2 | use chrono::Utc; |
| 3 | use gitolfs3_common::{generate_tag, load_key, Claims, Key, Operation, SpecificClaims}; | ||
| 3 | use serde_json::json; | 4 | use serde_json::json; |
| 4 | use std::{process::ExitCode, time::Duration}; | 5 | use std::{process::ExitCode, time::Duration}; |
| 5 | 6 | ||
| @@ -28,9 +29,9 @@ fn main() -> ExitCode { | |||
| 28 | } | 29 | } |
| 29 | 30 | ||
| 30 | let expires_at = Utc::now() + Duration::from_secs(5 * 60); | 31 | let expires_at = Utc::now() + Duration::from_secs(5 * 60); |
| 31 | let Some(tag) = common::generate_tag( | 32 | let Some(tag) = generate_tag( |
| 32 | common::Claims { | 33 | Claims { |
| 33 | specific_claims: common::SpecificClaims::BatchApi(operation), | 34 | specific_claims: SpecificClaims::BatchApi(operation), |
| 34 | repo_path: &repo_name, | 35 | repo_path: &repo_name, |
| 35 | expires_at, | 36 | expires_at, |
| 36 | }, | 37 | }, |
| @@ -57,7 +58,7 @@ fn main() -> ExitCode { | |||
| 57 | 58 | ||
| 58 | struct Config { | 59 | struct Config { |
| 59 | href_base: String, | 60 | href_base: String, |
| 60 | key: common::Key, | 61 | key: Key, |
| 61 | } | 62 | } |
| 62 | 63 | ||
| 63 | impl Config { | 64 | impl Config { |
| @@ -72,15 +73,15 @@ impl Config { | |||
| 72 | let Ok(key_path) = std::env::var("GITOLFS3_KEY_PATH") else { | 73 | let Ok(key_path) = std::env::var("GITOLFS3_KEY_PATH") else { |
| 73 | bail!("key path not provided"); | 74 | bail!("key path not provided"); |
| 74 | }; | 75 | }; |
| 75 | let key = common::load_key(&key_path).map_err(|e| anyhow!("failed to load key: {e}"))?; | 76 | let key = load_key(&key_path).map_err(|e| anyhow!("failed to load key: {e}"))?; |
| 76 | 77 | ||
| 77 | Ok(Self { href_base, key }) | 78 | Ok(Self { href_base, key }) |
| 78 | } | 79 | } |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 81 | fn parse_cmdline() -> Result<(String, common::Operation)> { | 82 | fn parse_cmdline() -> Result<(String, Operation)> { |
| 82 | let [repo_path, op_str] = get_cmdline_args::<2>()?; | 83 | let [repo_path, op_str] = get_cmdline_args::<2>()?; |
| 83 | let op: common::Operation = op_str | 84 | let op: Operation = op_str |
| 84 | .parse() | 85 | .parse() |
| 85 | .map_err(|e| anyhow!("unknown operation: {e}"))?; | 86 | .map_err(|e| anyhow!("unknown operation: {e}"))?; |
| 86 | validate_repo_path(&repo_path).map_err(|e| anyhow!("invalid repository name: {e}"))?; | 87 | validate_repo_path(&repo_path).map_err(|e| anyhow!("invalid repository name: {e}"))?; |
diff --git a/common/Cargo.toml b/gitolfs3-common/Cargo.toml index 20d9bdd..5724732 100644 --- a/common/Cargo.toml +++ b/gitolfs3-common/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | name = "common" | 2 | name = "gitolfs3-common" |
| 3 | version = "0.1.0" | 3 | version = "0.1.0" |
| 4 | edition = "2021" | 4 | edition = "2021" |
| 5 | 5 | ||
diff --git a/common/src/lib.rs b/gitolfs3-common/src/lib.rs index 917f566..917f566 100644 --- a/common/src/lib.rs +++ b/gitolfs3-common/src/lib.rs | |||
diff --git a/server/Cargo.toml b/gitolfs3-server/Cargo.toml index edb76d8..04edeea 100644 --- a/server/Cargo.toml +++ b/gitolfs3-server/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | name = "server" | 2 | name = "gitolfs3-server" |
| 3 | version = "0.1.0" | 3 | version = "0.1.0" |
| 4 | edition = "2021" | 4 | edition = "2021" |
| 5 | 5 | ||
| @@ -9,7 +9,7 @@ aws-sdk-s3 = "1.12.0" | |||
| 9 | axum = "0.7" | 9 | axum = "0.7" |
| 10 | base64 = "0.21" | 10 | base64 = "0.21" |
| 11 | chrono = { version = "0.4", features = ["serde"] } | 11 | chrono = { version = "0.4", features = ["serde"] } |
| 12 | common = { path = "../common" } | 12 | gitolfs3-common = { path = "../gitolfs3-common" } |
| 13 | mime = "0.3" | 13 | mime = "0.3" |
| 14 | serde = { version = "1", features = ["derive"] } | 14 | serde = { version = "1", features = ["derive"] } |
| 15 | serde_json = "1" | 15 | serde_json = "1" |
diff --git a/server/src/main.rs b/gitolfs3-server/src/main.rs index 7371c0d..b05a0c8 100644 --- a/server/src/main.rs +++ b/gitolfs3-server/src/main.rs | |||
| @@ -9,6 +9,9 @@ use axum::{ | |||
| 9 | }; | 9 | }; |
| 10 | use base64::prelude::*; | 10 | use base64::prelude::*; |
| 11 | use chrono::{DateTime, Utc}; | 11 | use chrono::{DateTime, Utc}; |
| 12 | use gitolfs3_common::{ | ||
| 13 | generate_tag, load_key, Claims, Digest, HexByte, Key, Oid, Operation, SpecificClaims, | ||
| 14 | }; | ||
| 12 | use serde::{ | 15 | use serde::{ |
| 13 | de::{self, DeserializeOwned}, | 16 | de::{self, DeserializeOwned}, |
| 14 | Deserialize, Serialize, | 17 | Deserialize, Serialize, |
| @@ -228,7 +231,7 @@ impl Config { | |||
| 228 | Ok(s3_client) => s3_client, | 231 | Ok(s3_client) => s3_client, |
| 229 | Err(e) => return Err(format!("failed to create S3 client: {e}")), | 232 | Err(e) => return Err(format!("failed to create S3 client: {e}")), |
| 230 | }; | 233 | }; |
| 231 | let key = match common::load_key(&env.key_path) { | 234 | let key = match load_key(&env.key_path) { |
| 232 | Ok(key) => key, | 235 | Ok(key) => key, |
| 233 | Err(e) => return Err(format!("failed to load Gitolfs3 key: {e}")), | 236 | Err(e) => return Err(format!("failed to load Gitolfs3 key: {e}")), |
| 234 | }; | 237 | }; |
| @@ -286,7 +289,7 @@ impl Default for HashAlgo { | |||
| 286 | 289 | ||
| 287 | #[derive(Debug, Deserialize, PartialEq, Eq, Clone)] | 290 | #[derive(Debug, Deserialize, PartialEq, Eq, Clone)] |
| 288 | struct BatchRequestObject { | 291 | struct BatchRequestObject { |
| 289 | oid: common::Oid, | 292 | oid: Oid, |
| 290 | size: i64, | 293 | size: i64, |
| 291 | } | 294 | } |
| 292 | 295 | ||
| @@ -301,7 +304,7 @@ fn default_transfers() -> Vec<TransferAdapter> { | |||
| 301 | 304 | ||
| 302 | #[derive(Debug, Deserialize, PartialEq, Eq, Clone)] | 305 | #[derive(Debug, Deserialize, PartialEq, Eq, Clone)] |
| 303 | struct BatchRequest { | 306 | struct BatchRequest { |
| 304 | operation: common::Operation, | 307 | operation: Operation, |
| 305 | #[serde(default = "default_transfers")] | 308 | #[serde(default = "default_transfers")] |
| 306 | transfers: Vec<TransferAdapter>, | 309 | transfers: Vec<TransferAdapter>, |
| 307 | objects: Vec<BatchRequestObject>, | 310 | objects: Vec<BatchRequestObject>, |
| @@ -426,7 +429,7 @@ struct BatchResponseObjectError { | |||
| 426 | 429 | ||
| 427 | #[derive(Debug, Serialize, Clone)] | 430 | #[derive(Debug, Serialize, Clone)] |
| 428 | struct BatchResponseObject { | 431 | struct BatchResponseObject { |
| 429 | oid: common::Oid, | 432 | oid: Oid, |
| 430 | size: i64, | 433 | size: i64, |
| 431 | #[serde(skip_serializing_if = "Option::is_none")] | 434 | #[serde(skip_serializing_if = "Option::is_none")] |
| 432 | authenticated: Option<bool>, | 435 | authenticated: Option<bool>, |
| @@ -457,11 +460,11 @@ struct BatchResponse { | |||
| 457 | hash_algo: HashAlgo, | 460 | hash_algo: HashAlgo, |
| 458 | } | 461 | } |
| 459 | 462 | ||
| 460 | fn validate_checksum(oid: common::Oid, obj: &HeadObjectOutput) -> bool { | 463 | fn validate_checksum(oid: Oid, obj: &HeadObjectOutput) -> bool { |
| 461 | if let Some(checksum) = obj.checksum_sha256() { | 464 | if let Some(checksum) = obj.checksum_sha256() { |
| 462 | if let Ok(checksum) = BASE64_STANDARD.decode(checksum) { | 465 | if let Ok(checksum) = BASE64_STANDARD.decode(checksum) { |
| 463 | if let Ok(checksum32b) = TryInto::<[u8; 32]>::try_into(checksum) { | 466 | if let Ok(checksum32b) = TryInto::<[u8; 32]>::try_into(checksum) { |
| 464 | return common::Oid::from(checksum32b) == oid; | 467 | return Oid::from(checksum32b) == oid; |
| 465 | } | 468 | } |
| 466 | } | 469 | } |
| 467 | } | 470 | } |
| @@ -480,7 +483,7 @@ async fn handle_upload_object( | |||
| 480 | repo: &str, | 483 | repo: &str, |
| 481 | obj: &BatchRequestObject, | 484 | obj: &BatchRequestObject, |
| 482 | ) -> Option<BatchResponseObject> { | 485 | ) -> Option<BatchResponseObject> { |
| 483 | let (oid0, oid1) = (common::HexByte(obj.oid[0]), common::HexByte(obj.oid[1])); | 486 | let (oid0, oid1) = (HexByte(obj.oid[0]), HexByte(obj.oid[1])); |
| 484 | let full_path = format!("{repo}/lfs/objects/{}/{}/{}", oid0, oid1, obj.oid); | 487 | let full_path = format!("{repo}/lfs/objects/{}/{}/{}", oid0, oid1, obj.oid); |
| 485 | 488 | ||
| 486 | match state | 489 | match state |
| @@ -559,7 +562,7 @@ async fn handle_download_object( | |||
| 559 | obj: &BatchRequestObject, | 562 | obj: &BatchRequestObject, |
| 560 | trusted: bool, | 563 | trusted: bool, |
| 561 | ) -> BatchResponseObject { | 564 | ) -> BatchResponseObject { |
| 562 | let (oid0, oid1) = (common::HexByte(obj.oid[0]), common::HexByte(obj.oid[1])); | 565 | let (oid0, oid1) = (HexByte(obj.oid[0]), HexByte(obj.oid[1])); |
| 563 | let full_path = format!("{repo}/lfs/objects/{}/{}/{}", oid0, oid1, obj.oid); | 566 | let full_path = format!("{repo}/lfs/objects/{}/{}/{}", oid0, oid1, obj.oid); |
| 564 | 567 | ||
| 565 | let result = match state | 568 | let result = match state |
| @@ -671,9 +674,9 @@ async fn handle_download_object( | |||
| 671 | } | 674 | } |
| 672 | } | 675 | } |
| 673 | 676 | ||
| 674 | let Some(tag) = common::generate_tag( | 677 | let Some(tag) = generate_tag( |
| 675 | common::Claims { | 678 | Claims { |
| 676 | specific_claims: common::SpecificClaims::Download(obj.oid), | 679 | specific_claims: SpecificClaims::Download(obj.oid), |
| 677 | repo_path: repo, | 680 | repo_path: repo, |
| 678 | expires_at, | 681 | expires_at, |
| 679 | }, | 682 | }, |
| @@ -688,8 +691,8 @@ async fn handle_download_object( | |||
| 688 | 691 | ||
| 689 | let upload_path = format!( | 692 | let upload_path = format!( |
| 690 | "{repo}/info/lfs/objects/{}/{}/{}", | 693 | "{repo}/info/lfs/objects/{}/{}/{}", |
| 691 | common::HexByte(obj.oid[0]), | 694 | HexByte(obj.oid[0]), |
| 692 | common::HexByte(obj.oid[1]), | 695 | HexByte(obj.oid[1]), |
| 693 | obj.oid, | 696 | obj.oid, |
| 694 | ); | 697 | ); |
| 695 | 698 | ||
| @@ -718,7 +721,7 @@ async fn handle_download_object( | |||
| 718 | 721 | ||
| 719 | struct AuthorizationConfig { | 722 | struct AuthorizationConfig { |
| 720 | trusted_forwarded_hosts: HashSet<String>, | 723 | trusted_forwarded_hosts: HashSet<String>, |
| 721 | key: common::Key, | 724 | key: Key, |
| 722 | } | 725 | } |
| 723 | 726 | ||
| 724 | struct Trusted(bool); | 727 | struct Trusted(bool); |
| @@ -749,7 +752,7 @@ fn authorize_batch( | |||
| 749 | conf: &AuthorizationConfig, | 752 | conf: &AuthorizationConfig, |
| 750 | repo_path: &str, | 753 | repo_path: &str, |
| 751 | public: bool, | 754 | public: bool, |
| 752 | operation: common::Operation, | 755 | operation: Operation, |
| 753 | headers: &HeaderMap, | 756 | headers: &HeaderMap, |
| 754 | ) -> Result<Trusted, GitLfsErrorResponse<'static>> { | 757 | ) -> Result<Trusted, GitLfsErrorResponse<'static>> { |
| 755 | // - No authentication required for downloading exported repos | 758 | // - No authentication required for downloading exported repos |
| @@ -759,7 +762,7 @@ fn authorize_batch( | |||
| 759 | // - No authentication required for downloading from any repo | 762 | // - No authentication required for downloading from any repo |
| 760 | 763 | ||
| 761 | let claims = VerifyClaimsInput { | 764 | let claims = VerifyClaimsInput { |
| 762 | specific_claims: common::SpecificClaims::BatchApi(operation), | 765 | specific_claims: SpecificClaims::BatchApi(operation), |
| 763 | repo_path, | 766 | repo_path, |
| 764 | }; | 767 | }; |
| 765 | if !verify_claims(conf, &claims, headers)? { | 768 | if !verify_claims(conf, &claims, headers)? { |
| @@ -771,12 +774,12 @@ fn authorize_batch( | |||
| 771 | fn authorize_batch_unauthenticated( | 774 | fn authorize_batch_unauthenticated( |
| 772 | conf: &AuthorizationConfig, | 775 | conf: &AuthorizationConfig, |
| 773 | public: bool, | 776 | public: bool, |
| 774 | operation: common::Operation, | 777 | operation: Operation, |
| 775 | headers: &HeaderMap, | 778 | headers: &HeaderMap, |
| 776 | ) -> Result<Trusted, GitLfsErrorResponse<'static>> { | 779 | ) -> Result<Trusted, GitLfsErrorResponse<'static>> { |
| 777 | let trusted = forwarded_from_trusted_host(headers, &conf.trusted_forwarded_hosts)?; | 780 | let trusted = forwarded_from_trusted_host(headers, &conf.trusted_forwarded_hosts)?; |
| 778 | match operation { | 781 | match operation { |
| 779 | common::Operation::Upload => { | 782 | Operation::Upload => { |
| 780 | // Trusted users can clone all repositories (by virtue of accessing the server via a | 783 | // Trusted users can clone all repositories (by virtue of accessing the server via a |
| 781 | // trusted network). However, they can not push without proper authentication. Untrusted | 784 | // trusted network). However, they can not push without proper authentication. Untrusted |
| 782 | // users who are also not authenticated should not need to know which repositories exists. | 785 | // users who are also not authenticated should not need to know which repositories exists. |
| @@ -790,7 +793,7 @@ fn authorize_batch_unauthenticated( | |||
| 790 | "Authentication required to upload", | 793 | "Authentication required to upload", |
| 791 | )) | 794 | )) |
| 792 | } | 795 | } |
| 793 | common::Operation::Download => { | 796 | Operation::Download => { |
| 794 | // Again, trusted users can see all repos. For untrusted users, we first need to check | 797 | // Again, trusted users can see all repos. For untrusted users, we first need to check |
| 795 | // whether the repo is public before we authorize. If the user is untrusted and the | 798 | // whether the repo is public before we authorize. If the user is untrusted and the |
| 796 | // repo isn't public, we just act like it doesn't even exist. | 799 | // repo isn't public, we just act like it doesn't even exist. |
| @@ -869,10 +872,10 @@ async fn batch( | |||
| 869 | }; | 872 | }; |
| 870 | for obj in payload.objects { | 873 | for obj in payload.objects { |
| 871 | match payload.operation { | 874 | match payload.operation { |
| 872 | common::Operation::Download => resp | 875 | Operation::Download => resp |
| 873 | .objects | 876 | .objects |
| 874 | .push(handle_download_object(&state, &repo, &obj, trusted).await), | 877 | .push(handle_download_object(&state, &repo, &obj, trusted).await), |
| 875 | common::Operation::Upload => { | 878 | Operation::Upload => { |
| 876 | if let Some(obj_resp) = handle_upload_object(&state, &repo, &obj).await { | 879 | if let Some(obj_resp) = handle_upload_object(&state, &repo, &obj).await { |
| 877 | resp.objects.push(obj_resp); | 880 | resp.objects.push(obj_resp); |
| 878 | } | 881 | } |
| @@ -885,9 +888,9 @@ async fn batch( | |||
| 885 | #[derive(Deserialize, Copy, Clone)] | 888 | #[derive(Deserialize, Copy, Clone)] |
| 886 | #[serde(remote = "Self")] | 889 | #[serde(remote = "Self")] |
| 887 | struct FileParams { | 890 | struct FileParams { |
| 888 | oid0: common::HexByte, | 891 | oid0: HexByte, |
| 889 | oid1: common::HexByte, | 892 | oid1: HexByte, |
| 890 | oid: common::Oid, | 893 | oid: Oid, |
| 891 | } | 894 | } |
| 892 | 895 | ||
| 893 | impl<'de> Deserialize<'de> for FileParams { | 896 | impl<'de> Deserialize<'de> for FileParams { |
| @@ -896,8 +899,8 @@ impl<'de> Deserialize<'de> for FileParams { | |||
| 896 | D: serde::Deserializer<'de>, | 899 | D: serde::Deserializer<'de>, |
| 897 | { | 900 | { |
| 898 | let unchecked @ FileParams { | 901 | let unchecked @ FileParams { |
| 899 | oid0: common::HexByte(oid0), | 902 | oid0: HexByte(oid0), |
| 900 | oid1: common::HexByte(oid1), | 903 | oid1: HexByte(oid1), |
| 901 | oid, | 904 | oid, |
| 902 | } = FileParams::deserialize(deserializer)?; | 905 | } = FileParams::deserialize(deserializer)?; |
| 903 | if oid0 != oid.as_bytes()[0] { | 906 | if oid0 != oid.as_bytes()[0] { |
| @@ -915,7 +918,7 @@ impl<'de> Deserialize<'de> for FileParams { | |||
| 915 | } | 918 | } |
| 916 | 919 | ||
| 917 | pub struct VerifyClaimsInput<'a> { | 920 | pub struct VerifyClaimsInput<'a> { |
| 918 | pub specific_claims: common::SpecificClaims, | 921 | pub specific_claims: SpecificClaims, |
| 919 | pub repo_path: &'a str, | 922 | pub repo_path: &'a str, |
| 920 | } | 923 | } |
| 921 | 924 | ||
| @@ -935,11 +938,11 @@ fn verify_claims( | |||
| 935 | .strip_prefix("Gitolfs3-Hmac-Sha256 ") | 938 | .strip_prefix("Gitolfs3-Hmac-Sha256 ") |
| 936 | .ok_or(INVALID_AUTHZ_HEADER)?; | 939 | .ok_or(INVALID_AUTHZ_HEADER)?; |
| 937 | let (tag, expires_at) = val.split_once(' ').ok_or(INVALID_AUTHZ_HEADER)?; | 940 | let (tag, expires_at) = val.split_once(' ').ok_or(INVALID_AUTHZ_HEADER)?; |
| 938 | let tag: common::Digest<32> = tag.parse().map_err(|_| INVALID_AUTHZ_HEADER)?; | 941 | let tag: Digest<32> = tag.parse().map_err(|_| INVALID_AUTHZ_HEADER)?; |
| 939 | let expires_at: i64 = expires_at.parse().map_err(|_| INVALID_AUTHZ_HEADER)?; | 942 | let expires_at: i64 = expires_at.parse().map_err(|_| INVALID_AUTHZ_HEADER)?; |
| 940 | let expires_at = DateTime::<Utc>::from_timestamp(expires_at, 0).ok_or(INVALID_AUTHZ_HEADER)?; | 943 | let expires_at = DateTime::<Utc>::from_timestamp(expires_at, 0).ok_or(INVALID_AUTHZ_HEADER)?; |
| 941 | let expected_tag = common::generate_tag( | 944 | let expected_tag = generate_tag( |
| 942 | common::Claims { | 945 | Claims { |
| 943 | specific_claims: claims.specific_claims, | 946 | specific_claims: claims.specific_claims, |
| 944 | repo_path: claims.repo_path, | 947 | repo_path: claims.repo_path, |
| 945 | expires_at, | 948 | expires_at, |
| @@ -957,11 +960,11 @@ fn verify_claims( | |||
| 957 | fn authorize_get( | 960 | fn authorize_get( |
| 958 | conf: &AuthorizationConfig, | 961 | conf: &AuthorizationConfig, |
| 959 | repo_path: &str, | 962 | repo_path: &str, |
| 960 | oid: common::Oid, | 963 | oid: Oid, |
| 961 | headers: &HeaderMap, | 964 | headers: &HeaderMap, |
| 962 | ) -> Result<(), GitLfsErrorResponse<'static>> { | 965 | ) -> Result<(), GitLfsErrorResponse<'static>> { |
| 963 | let claims = VerifyClaimsInput { | 966 | let claims = VerifyClaimsInput { |
| 964 | specific_claims: common::SpecificClaims::Download(oid), | 967 | specific_claims: SpecificClaims::Download(oid), |
| 965 | repo_path, | 968 | repo_path, |
| 966 | }; | 969 | }; |
| 967 | if !verify_claims(conf, &claims, headers)? { | 970 | if !verify_claims(conf, &claims, headers)? { |
| @@ -1100,7 +1103,7 @@ fn test_deserialize() { | |||
| 1100 | let json = r#"{"operation":"upload","objects":[{"oid":"8f4123f9a7181f488c5e111d82cefd992e461ae5df01fd2254399e6e670b2d3c","size":170904}], | 1103 | let json = r#"{"operation":"upload","objects":[{"oid":"8f4123f9a7181f488c5e111d82cefd992e461ae5df01fd2254399e6e670b2d3c","size":170904}], |
| 1101 | "transfers":["lfs-standalone-file","basic","ssh"],"ref":{"name":"refs/heads/main"},"hash_algo":"sha256"}"#; | 1104 | "transfers":["lfs-standalone-file","basic","ssh"],"ref":{"name":"refs/heads/main"},"hash_algo":"sha256"}"#; |
| 1102 | let expected = BatchRequest { | 1105 | let expected = BatchRequest { |
| 1103 | operation: common::Operation::Upload, | 1106 | operation: Operation::Upload, |
| 1104 | objects: vec![BatchRequestObject { | 1107 | objects: vec![BatchRequestObject { |
| 1105 | oid: "8f4123f9a7181f488c5e111d82cefd992e461ae5df01fd2254399e6e670b2d3c" | 1108 | oid: "8f4123f9a7181f488c5e111d82cefd992e461ae5df01fd2254399e6e670b2d3c" |
| 1106 | .parse() | 1109 | .parse() |
| @@ -1123,14 +1126,14 @@ fn test_deserialize() { | |||
| 1123 | #[test] | 1126 | #[test] |
| 1124 | fn test_validate_claims() { | 1127 | fn test_validate_claims() { |
| 1125 | let key = "00232f7a019bd34e3921ee6c5f04caf48a4489d1be5d1999038950a7054e0bfea369ce2becc0f13fd3c69f8af2384a25b7ac2d52eb52c33722f3c00c50d4c9c2"; | 1128 | let key = "00232f7a019bd34e3921ee6c5f04caf48a4489d1be5d1999038950a7054e0bfea369ce2becc0f13fd3c69f8af2384a25b7ac2d52eb52c33722f3c00c50d4c9c2"; |
| 1126 | let key: common::Key = key.parse().unwrap(); | 1129 | let key: Key = key.parse().unwrap(); |
| 1127 | 1130 | ||
| 1128 | let claims = common::Claims { | 1131 | let claims = Claims { |
| 1129 | expires_at: Utc::now() + std::time::Duration::from_secs(5 * 60), | 1132 | expires_at: Utc::now() + std::time::Duration::from_secs(5 * 60), |
| 1130 | repo_path: "lfs-test.git", | 1133 | repo_path: "lfs-test.git", |
| 1131 | specific_claims: common::SpecificClaims::BatchApi(common::Operation::Download), | 1134 | specific_claims: SpecificClaims::BatchApi(Operation::Download), |
| 1132 | }; | 1135 | }; |
| 1133 | let tag = common::generate_tag(claims, &key).unwrap(); | 1136 | let tag = generate_tag(claims, &key).unwrap(); |
| 1134 | let header_value = format!( | 1137 | let header_value = format!( |
| 1135 | "Gitolfs3-Hmac-Sha256 {tag} {}", | 1138 | "Gitolfs3-Hmac-Sha256 {tag} {}", |
| 1136 | claims.expires_at.timestamp() | 1139 | claims.expires_at.timestamp() |
diff --git a/shell/Cargo.toml b/gitolfs3-shell/Cargo.toml index 0dcb6d6..c0b5d3a 100644 --- a/shell/Cargo.toml +++ b/gitolfs3-shell/Cargo.toml | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | name = "shell" | 2 | name = "gitolfs3-shell" |
| 3 | version = "0.1.0" | 3 | version = "0.1.0" |
| 4 | edition = "2021" | 4 | edition = "2021" |
| 5 | 5 | ||
diff --git a/shell/src/main.rs b/gitolfs3-shell/src/main.rs index 4a98828..f0c5f34 100644 --- a/shell/src/main.rs +++ b/gitolfs3-shell/src/main.rs | |||
| @@ -46,6 +46,8 @@ fn main() -> ExitCode { | |||
| 46 | let repository = cmd[0].trim_start_matches('/'); | 46 | let repository = cmd[0].trim_start_matches('/'); |
| 47 | args.push(repository); | 47 | args.push(repository); |
| 48 | } else if program == "git-lfs-authenticate" { | 48 | } else if program == "git-lfs-authenticate" { |
| 49 | program.clear(); | ||
| 50 | program.push_str("gitolfs3-authenticate"); | ||
| 49 | if cmd.len() != 2 { | 51 | if cmd.len() != 2 { |
| 50 | eprintln!("Bad command"); | 52 | eprintln!("Bad command"); |
| 51 | return bad_usage; | 53 | return bad_usage; |