Merge pull request #135 from cole-h/token-use-indexmap
token: switch to using IndexMap for consistent ordering of entries
This commit is contained in:
commit
ec0469cad0
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -351,6 +351,7 @@ dependencies = [
|
||||||
"base64 0.21.5",
|
"base64 0.21.5",
|
||||||
"chrono",
|
"chrono",
|
||||||
"displaydoc",
|
"displaydoc",
|
||||||
|
"indexmap 2.2.6",
|
||||||
"jwt-simple",
|
"jwt-simple",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -2204,9 +2205,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.1.0"
|
version = "2.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.14.2",
|
"hashbrown 0.14.2",
|
||||||
|
@ -3680,7 +3681,7 @@ dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"hex",
|
"hex",
|
||||||
"indexmap 1.9.3",
|
"indexmap 1.9.3",
|
||||||
"indexmap 2.1.0",
|
"indexmap 2.2.6",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_with_macros",
|
"serde_with_macros",
|
||||||
|
@ -3705,7 +3706,7 @@ version = "0.9.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c"
|
checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.1.0",
|
"indexmap 2.2.6",
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -3912,7 +3913,7 @@ dependencies = [
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hashlink",
|
"hashlink",
|
||||||
"hex",
|
"hex",
|
||||||
"indexmap 2.1.0",
|
"indexmap 2.2.6",
|
||||||
"log",
|
"log",
|
||||||
"memchr",
|
"memchr",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
@ -4404,7 +4405,7 @@ version = "0.21.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"
|
checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.1.0",
|
"indexmap 2.2.6",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_spanned",
|
"serde_spanned",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
|
|
|
@ -11,6 +11,7 @@ attic = { path = "../attic", default-features = false }
|
||||||
base64 = "0.21.2"
|
base64 = "0.21.2"
|
||||||
chrono = "0.4.24"
|
chrono = "0.4.24"
|
||||||
displaydoc = "0.2.4"
|
displaydoc = "0.2.4"
|
||||||
|
indexmap = { version = "2.2.6", features = ["serde"] }
|
||||||
jwt-simple = "0.11.5"
|
jwt-simple = "0.11.5"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
regex = "1.8.3"
|
regex = "1.8.3"
|
||||||
|
|
|
@ -83,12 +83,12 @@ pub mod util;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
|
|
||||||
use base64::{engine::general_purpose::STANDARD as BASE64_STANDARD, Engine};
|
use base64::{engine::general_purpose::STANDARD as BASE64_STANDARD, Engine};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use displaydoc::Display;
|
use displaydoc::Display;
|
||||||
|
use indexmap::IndexMap;
|
||||||
pub use jwt_simple::{
|
pub use jwt_simple::{
|
||||||
algorithms::{HS256Key, MACLike},
|
algorithms::{HS256Key, MACLike},
|
||||||
claims::{Claims, JWTClaims},
|
claims::{Claims, JWTClaims},
|
||||||
|
@ -146,7 +146,7 @@ pub struct AtticAccess {
|
||||||
/// Cache permissions.
|
/// Cache permissions.
|
||||||
///
|
///
|
||||||
/// Keys here may include wildcards.
|
/// Keys here may include wildcards.
|
||||||
caches: HashMap<CacheNamePattern, CachePermission>,
|
caches: IndexMap<CacheNamePattern, CachePermission>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Permission to a single cache.
|
/// Permission to a single cache.
|
||||||
|
@ -274,7 +274,7 @@ impl Token {
|
||||||
&mut self,
|
&mut self,
|
||||||
pattern: CacheNamePattern,
|
pattern: CacheNamePattern,
|
||||||
) -> &mut CachePermission {
|
) -> &mut CachePermission {
|
||||||
use std::collections::hash_map::Entry;
|
use indexmap::map::Entry;
|
||||||
|
|
||||||
let access = self.attic_access_mut();
|
let access = self.attic_access_mut();
|
||||||
match access.caches.entry(pattern) {
|
match access.caches.entry(pattern) {
|
||||||
|
|
|
@ -21,6 +21,8 @@ fn test_basic() {
|
||||||
"exp": 4102324986,
|
"exp": 4102324986,
|
||||||
"https://jwt.attic.rs/v1": {
|
"https://jwt.attic.rs/v1": {
|
||||||
"caches": {
|
"caches": {
|
||||||
|
"all-*": {"r":1},
|
||||||
|
"all-ci-*": {"w":1},
|
||||||
"cache-rw": {"r":1,"w":1},
|
"cache-rw": {"r":1,"w":1},
|
||||||
"cache-ro": {"r":1},
|
"cache-ro": {"r":1},
|
||||||
"team-*": {"r":1,"w":1,"cc":1}
|
"team-*": {"r":1,"w":1,"cc":1}
|
||||||
|
@ -29,7 +31,29 @@ fn test_basic() {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJtZW93IiwiZXhwIjo0MTAyMzI0OTg2LCJodHRwczovL2p3dC5hdHRpYy5ycy92MSI6eyJjYWNoZXMiOnsiY2FjaGUtcnciOnsiciI6MSwidyI6MX0sImNhY2hlLXJvIjp7InIiOjF9LCJ0ZWFtLSoiOnsiciI6MSwidyI6MSwiY2MiOjF9fX19.UlsIM9bQHr9SXGAcSQcoVPo9No8Zhh6Y5xfX8vCmKmA";
|
let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjQxMDIzMjQ5ODYsImh0dHBzOi8vand0LmF0dGljLnJzL3YxIjp7ImNhY2hlcyI6eyJhbGwtKiI6eyJyIjoxfSwiYWxsLWNpLSoiOnsidyI6MX0sImNhY2hlLXJvIjp7InIiOjF9LCJjYWNoZS1ydyI6eyJyIjoxLCJ3IjoxfSwidGVhbS0qIjp7ImNjIjoxLCJyIjoxLCJ3IjoxfX19LCJpYXQiOjE3MTY2NjA1ODksInN1YiI6Im1lb3cifQ.8vtxp_1OEYdcnkGPM4c9ORXooJZV7DOTS4NRkMKN8mw";
|
||||||
|
|
||||||
|
// NOTE(cole-h): check that we get a consistent iteration order when getting permissions for
|
||||||
|
// caches -- this depends on the order of the fields in the token, but should otherwise be
|
||||||
|
// consistent between iterations
|
||||||
|
let mut was_ever_wrong = false;
|
||||||
|
for _ in 0..=1_000 {
|
||||||
|
// NOTE(cole-h): we construct a new Token every iteration in order to get different "random
|
||||||
|
// state"
|
||||||
|
let decoded = Token::from_jwt(token, &dec_key).unwrap();
|
||||||
|
let perm_all_ci = decoded.get_permission_for_cache(&cache! { "all-ci-abc" });
|
||||||
|
|
||||||
|
// NOTE(cole-h): if the iteration order of the token is inconsistent, the permissions may be
|
||||||
|
// retrieved from the `all-ci-*` pattern (which only allows writing/pushing), even though
|
||||||
|
// the `all-*` pattern (which only allows reading/pulling) is specified first
|
||||||
|
if perm_all_ci.require_pull().is_err() || perm_all_ci.require_push().is_ok() {
|
||||||
|
was_ever_wrong = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert!(
|
||||||
|
!was_ever_wrong,
|
||||||
|
"Iteration order should be consistent to prevent random auth failures (and successes)"
|
||||||
|
);
|
||||||
|
|
||||||
let decoded = Token::from_jwt(token, &dec_key).unwrap();
|
let decoded = Token::from_jwt(token, &dec_key).unwrap();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue