A fork of attic a self-hostable Nix Binary Cache server
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #135 from cole-h/token-use-indexmap

token: switch to using IndexMap for consistent ordering of entries

authored by

Zhaofeng Li and committed by
GitHub
ec0469ca 05582693

+36 -10
+7 -6
Cargo.lock
··· 351 351 "base64 0.21.5", 352 352 "chrono", 353 353 "displaydoc", 354 + "indexmap 2.2.6", 354 355 "jwt-simple", 355 356 "lazy_static", 356 357 "regex", ··· 2204 2205 2205 2206 [[package]] 2206 2207 name = "indexmap" 2207 - version = "2.1.0" 2208 + version = "2.2.6" 2208 2209 source = "registry+https://github.com/rust-lang/crates.io-index" 2209 - checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" 2210 + checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" 2210 2211 dependencies = [ 2211 2212 "equivalent", 2212 2213 "hashbrown 0.14.2", ··· 3680 3681 "chrono", 3681 3682 "hex", 3682 3683 "indexmap 1.9.3", 3683 - "indexmap 2.1.0", 3684 + "indexmap 2.2.6", 3684 3685 "serde", 3685 3686 "serde_json", 3686 3687 "serde_with_macros", ··· 3705 3706 source = "registry+https://github.com/rust-lang/crates.io-index" 3706 3707 checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" 3707 3708 dependencies = [ 3708 - "indexmap 2.1.0", 3709 + "indexmap 2.2.6", 3709 3710 "itoa", 3710 3711 "ryu", 3711 3712 "serde", ··· 3912 3913 "futures-util", 3913 3914 "hashlink", 3914 3915 "hex", 3915 - "indexmap 2.1.0", 3916 + "indexmap 2.2.6", 3916 3917 "log", 3917 3918 "memchr", 3918 3919 "once_cell", ··· 4404 4405 source = "registry+https://github.com/rust-lang/crates.io-index" 4405 4406 checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" 4406 4407 dependencies = [ 4407 - "indexmap 2.1.0", 4408 + "indexmap 2.2.6", 4408 4409 "serde", 4409 4410 "serde_spanned", 4410 4411 "toml_datetime",
+1
token/Cargo.toml
··· 11 11 base64 = "0.21.2" 12 12 chrono = "0.4.24" 13 13 displaydoc = "0.2.4" 14 + indexmap = { version = "2.2.6", features = ["serde"] } 14 15 jwt-simple = "0.11.5" 15 16 lazy_static = "1.4.0" 16 17 regex = "1.8.3"
+3 -3
token/src/lib.rs
··· 83 83 #[cfg(test)] 84 84 mod tests; 85 85 86 - use std::collections::HashMap; 87 86 use std::error::Error as StdError; 88 87 89 88 use base64::{engine::general_purpose::STANDARD as BASE64_STANDARD, Engine}; 90 89 use chrono::{DateTime, Utc}; 91 90 use displaydoc::Display; 91 + use indexmap::IndexMap; 92 92 pub use jwt_simple::{ 93 93 algorithms::{HS256Key, MACLike}, 94 94 claims::{Claims, JWTClaims}, ··· 146 146 /// Cache permissions. 147 147 /// 148 148 /// Keys here may include wildcards. 149 - caches: HashMap<CacheNamePattern, CachePermission>, 149 + caches: IndexMap<CacheNamePattern, CachePermission>, 150 150 } 151 151 152 152 /// Permission to a single cache. ··· 274 274 &mut self, 275 275 pattern: CacheNamePattern, 276 276 ) -> &mut CachePermission { 277 - use std::collections::hash_map::Entry; 277 + use indexmap::map::Entry; 278 278 279 279 let access = self.attic_access_mut(); 280 280 match access.caches.entry(pattern) {
+25 -1
token/src/tests.rs
··· 21 21 "exp": 4102324986, 22 22 "https://jwt.attic.rs/v1": { 23 23 "caches": { 24 + "all-*": {"r":1}, 25 + "all-ci-*": {"w":1}, 24 26 "cache-rw": {"r":1,"w":1}, 25 27 "cache-ro": {"r":1}, 26 28 "team-*": {"r":1,"w":1,"cc":1} ··· 29 31 } 30 32 */ 31 33 32 - let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtZW93IiwiZXhwIjo0MTAyMzI0OTg2LCJodHRwczovL2p3dC5hdHRpYy5ycy92MSI6eyJjYWNoZXMiOnsiY2FjaGUtcnciOnsiciI6MSwidyI6MX0sImNhY2hlLXJvIjp7InIiOjF9LCJ0ZWFtLSoiOnsiciI6MSwidyI6MSwiY2MiOjF9fX19.UlsIM9bQHr9SXGAcSQcoVPo9No8Zhh6Y5xfX8vCmKmA"; 34 + let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjQxMDIzMjQ5ODYsImh0dHBzOi8vand0LmF0dGljLnJzL3YxIjp7ImNhY2hlcyI6eyJhbGwtKiI6eyJyIjoxfSwiYWxsLWNpLSoiOnsidyI6MX0sImNhY2hlLXJvIjp7InIiOjF9LCJjYWNoZS1ydyI6eyJyIjoxLCJ3IjoxfSwidGVhbS0qIjp7ImNjIjoxLCJyIjoxLCJ3IjoxfX19LCJpYXQiOjE3MTY2NjA1ODksInN1YiI6Im1lb3cifQ.8vtxp_1OEYdcnkGPM4c9ORXooJZV7DOTS4NRkMKN8mw"; 35 + 36 + // NOTE(cole-h): check that we get a consistent iteration order when getting permissions for 37 + // caches -- this depends on the order of the fields in the token, but should otherwise be 38 + // consistent between iterations 39 + let mut was_ever_wrong = false; 40 + for _ in 0..=1_000 { 41 + // NOTE(cole-h): we construct a new Token every iteration in order to get different "random 42 + // state" 43 + let decoded = Token::from_jwt(token, &dec_key).unwrap(); 44 + let perm_all_ci = decoded.get_permission_for_cache(&cache! { "all-ci-abc" }); 45 + 46 + // NOTE(cole-h): if the iteration order of the token is inconsistent, the permissions may be 47 + // retrieved from the `all-ci-*` pattern (which only allows writing/pushing), even though 48 + // the `all-*` pattern (which only allows reading/pulling) is specified first 49 + if perm_all_ci.require_pull().is_err() || perm_all_ci.require_push().is_ok() { 50 + was_ever_wrong = true; 51 + } 52 + } 53 + assert!( 54 + !was_ever_wrong, 55 + "Iteration order should be consistent to prevent random auth failures (and successes)" 56 + ); 33 57 34 58 let decoded = Token::from_jwt(token, &dec_key).unwrap(); 35 59