feat: Change Bearer Auth Token to use random bits (#24733)
This changes the 'influxdb3 create token' command so that it will just automatically generate a completely random base64 encoded token prepended with 'apiv3_' that is then fed into a Sha512 algorithm instead of Sha256. The user can no longer pass in a token to be turned into the proper output. This also changes the server code to handle the change to Sha512 as well. Closes #24704pull/24737/head
parent
971676b498
commit
ce8c158956
|
@ -223,7 +223,7 @@ dependencies = [
|
|||
"arrow-data",
|
||||
"arrow-schema",
|
||||
"arrow-select",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"chrono",
|
||||
"comfy-table",
|
||||
"half",
|
||||
|
@ -279,7 +279,7 @@ dependencies = [
|
|||
"arrow-schema",
|
||||
"arrow-select",
|
||||
"arrow-string",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"futures",
|
||||
"once_cell",
|
||||
|
@ -538,7 +538,7 @@ source = "git+https://github.com/influxdata/influxdb3_core?rev=86d72868fd39f7865
|
|||
dependencies = [
|
||||
"async-trait",
|
||||
"backoff 0.1.0",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"generated_types",
|
||||
"http",
|
||||
"iox_time",
|
||||
|
@ -644,6 +644,12 @@ version = "0.21.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.6.0"
|
||||
|
@ -882,9 +888,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
|||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.34"
|
||||
version = "0.4.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b"
|
||||
checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
|
@ -1475,7 +1481,7 @@ version = "36.0.0"
|
|||
source = "git+https://github.com/apache/arrow-datafusion.git?rev=91f3eb2e5430d23e2b551e66732bec1a3a575971#91f3eb2e5430d23e2b551e66732bec1a3a575971"
|
||||
dependencies = [
|
||||
"arrow",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"datafusion-common",
|
||||
"datafusion-execution",
|
||||
"datafusion-expr",
|
||||
|
@ -1525,7 +1531,7 @@ dependencies = [
|
|||
"arrow-ord",
|
||||
"arrow-schema",
|
||||
"arrow-string",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"blake2",
|
||||
"blake3",
|
||||
"chrono",
|
||||
|
@ -2197,7 +2203,7 @@ version = "7.5.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"byteorder",
|
||||
"flate2",
|
||||
"nom",
|
||||
|
@ -2464,6 +2470,7 @@ dependencies = [
|
|||
"arrow_util",
|
||||
"assert_cmd",
|
||||
"backtrace",
|
||||
"base64 0.22.0",
|
||||
"clap",
|
||||
"clap_blocks",
|
||||
"console-subscriber",
|
||||
|
@ -2488,6 +2495,7 @@ dependencies = [
|
|||
"parking_lot",
|
||||
"parquet_file",
|
||||
"pretty_assertions",
|
||||
"rand",
|
||||
"reqwest",
|
||||
"secrecy",
|
||||
"sha2",
|
||||
|
@ -2532,6 +2540,7 @@ dependencies = [
|
|||
"arrow-schema",
|
||||
"async-trait",
|
||||
"authz",
|
||||
"base64 0.22.0",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"data_types",
|
||||
|
@ -2663,7 +2672,7 @@ version = "0.1.0"
|
|||
source = "git+https://github.com/influxdata/influxdb3_core?rev=86d72868fd39f7865e97d0b3a66bac29a5f662b2#86d72868fd39f7865e97d0b3a66bac29a5f662b2"
|
||||
dependencies = [
|
||||
"arrow",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"data_types",
|
||||
"datafusion",
|
||||
|
@ -3003,7 +3012,7 @@ version = "0.21.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "550f99d93aa4c2b25de527bce492d772caf5e21d7ac9bd4b508ba781c8d91e30"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"chrono",
|
||||
"schemars",
|
||||
"serde",
|
||||
|
@ -3050,7 +3059,7 @@ version = "0.88.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fe0d65dd6f3adba29cfb84f19dfe55449c7f6c35425f9d8294bec40313e0b64"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"either",
|
||||
|
@ -3731,7 +3740,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "b8718f8b65fdf67a45108d1548347d4af7d71fb81ce727bbf9e3b2535e079db3"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"futures",
|
||||
|
@ -3856,7 +3865,7 @@ dependencies = [
|
|||
"arrow-ipc",
|
||||
"arrow-schema",
|
||||
"arrow-select",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"brotli",
|
||||
"bytes",
|
||||
"chrono",
|
||||
|
@ -3924,7 +3933,7 @@ version = "0.1.0"
|
|||
source = "git+https://github.com/influxdata/influxdb3_core?rev=86d72868fd39f7865e97d0b3a66bac29a5f662b2#86d72868fd39f7865e97d0b3a66bac29a5f662b2"
|
||||
dependencies = [
|
||||
"arrow",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"data_types",
|
||||
"datafusion",
|
||||
|
@ -3968,7 +3977,7 @@ version = "0.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1030c719b0ec2a2d25a5df729d6cff1acf3cc230bf766f4f97833591f7577b90"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"serde",
|
||||
]
|
||||
|
||||
|
@ -4005,7 +4014,7 @@ version = "3.0.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"serde",
|
||||
]
|
||||
|
||||
|
@ -4621,7 +4630,7 @@ version = "0.11.24"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
|
@ -4761,7 +4770,7 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4770,7 +4779,7 @@ version = "2.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f48172685e6ff52a556baa527774f61fcaa884f59daf3375c62a3f1cd2549dab"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
|
@ -5411,7 +5420,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bitflags 2.4.2",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
|
@ -5454,7 +5463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bitflags 2.4.2",
|
||||
"byteorder",
|
||||
"crc",
|
||||
|
@ -5974,7 +5983,7 @@ checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a"
|
|||
dependencies = [
|
||||
"async-trait",
|
||||
"axum",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
|
@ -6003,7 +6012,7 @@ dependencies = [
|
|||
"async-stream",
|
||||
"async-trait",
|
||||
"axum",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"h2",
|
||||
"http",
|
||||
|
@ -6090,7 +6099,7 @@ version = "0.4.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61c5bb1d698276a2443e5ecfabc1008bf15a36c12e6a7176e7bf089ea9131140"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bitflags 2.4.2",
|
||||
"bytes",
|
||||
"futures-core",
|
||||
|
@ -6818,7 +6827,7 @@ dependencies = [
|
|||
"ahash",
|
||||
"arrow",
|
||||
"arrow-ipc",
|
||||
"base64",
|
||||
"base64 0.21.7",
|
||||
"bit-set",
|
||||
"bit-vec",
|
||||
"bitflags 2.4.2",
|
||||
|
|
|
@ -39,6 +39,7 @@ arrow-schema = "50.0.0"
|
|||
assert_cmd = "2.0.14"
|
||||
async-trait = "0.1"
|
||||
backtrace = "0.3"
|
||||
base64 = "0.22.0"
|
||||
byteorder = "1.3.4"
|
||||
bytes = "1.5"
|
||||
chrono = "0.4"
|
||||
|
@ -70,6 +71,7 @@ pretty_assertions = "1.4.0"
|
|||
prost = "0.12.3"
|
||||
prost-build = "0.12.2"
|
||||
prost-types = "0.12.3"
|
||||
rand = "0.8.5"
|
||||
reqwest = { version = "0.11.24", default-features = false, features = ["rustls-tls"] }
|
||||
secrecy = "0.8.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
|
|
@ -28,6 +28,7 @@ influxdb3_write = { path = "../influxdb3_write" }
|
|||
|
||||
# Crates.io dependencies
|
||||
backtrace.workspace = true
|
||||
base64.workspace = true
|
||||
clap.workspace = true
|
||||
dotenvy.workspace = true
|
||||
hex.workspace = true
|
||||
|
@ -35,6 +36,7 @@ libc.workspace = true
|
|||
num_cpus.workspace = true
|
||||
once_cell.workspace = true
|
||||
parking_lot.workspace = true
|
||||
rand.workspace = true
|
||||
secrecy.workspace = true
|
||||
sha2.workspace = true
|
||||
thiserror.workspace = true
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
use base64::engine::general_purpose::URL_SAFE_NO_PAD as B64;
|
||||
use base64::Engine as _;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::RngCore;
|
||||
use sha2::Digest;
|
||||
use sha2::Sha256;
|
||||
use sha2::Sha512;
|
||||
use std::error::Error;
|
||||
use std::str;
|
||||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
pub struct Config {
|
||||
|
@ -10,25 +15,28 @@ pub struct Config {
|
|||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
pub enum SubCommand {
|
||||
Token { token: String },
|
||||
Token,
|
||||
}
|
||||
|
||||
pub fn command(config: Config) -> Result<(), Box<dyn Error>> {
|
||||
match config.cmd {
|
||||
SubCommand::Token { token } => {
|
||||
if token.is_empty() {
|
||||
return Err("Token argument must not be empty".into());
|
||||
}
|
||||
|
||||
SubCommand::Token => {
|
||||
let token = {
|
||||
let mut token = String::from("apiv3_");
|
||||
let mut key = [0u8; 64];
|
||||
OsRng.fill_bytes(&mut key);
|
||||
token.push_str(&B64.encode(key));
|
||||
token
|
||||
};
|
||||
println!(
|
||||
"\
|
||||
Token Input: {token}\n\
|
||||
Hashed Output: {hashed}\n\n\
|
||||
Token: {token}\n\
|
||||
Hashed Token: {hashed}\n\n\
|
||||
Start the server with `influxdb3 serve --bearer-token {hashed}`\n\n\
|
||||
HTTP requests require the following header: \"Authorization: Bearer {token}\"\n\
|
||||
This will grant you access to every HTTP endpoint or deny it otherwise
|
||||
",
|
||||
hashed = hex::encode(&Sha256::digest(&token)[..])
|
||||
hashed = hex::encode(&Sha512::digest(&token)[..])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@ static COMMAND: Mutex<Option<DropCommand>> = parking_lot::const_mutex(None);
|
|||
|
||||
#[tokio::test]
|
||||
async fn auth() {
|
||||
const HASHED_TOKEN: &str = "5315f0c4714537843face80cca8c18e27ce88e31e9be7a5232dc4dc8444f27c0227a9bd64831d3ab58f652bd0262dd8558dd08870ac9e5c650972ce9e4259439";
|
||||
const TOKEN: &str = "apiv3_mp75KQAhbqv0GeQXk8MPuZ3ztaLEaR5JzS8iifk1FwuroSVyXXyrJK1c4gEr1kHkmbgzDV-j3MvQpaIMVJBAiA";
|
||||
// The binary is made before testing so we have access to it
|
||||
let bin_path = {
|
||||
let mut bin_path = env::current_exe().unwrap();
|
||||
|
@ -41,10 +43,10 @@ async fn auth() {
|
|||
"--object-store",
|
||||
"memory",
|
||||
"--bearer-token",
|
||||
"2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae", // foo as a sha256
|
||||
HASHED_TOKEN,
|
||||
])
|
||||
.stderr(Stdio::null())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.spawn()
|
||||
.expect("Was able to spawn a server"),
|
||||
);
|
||||
|
@ -62,7 +64,7 @@ async fn auth() {
|
|||
// Wait for the server to come up
|
||||
while client
|
||||
.get("http://127.0.0.1:8181/health")
|
||||
.bearer_auth("foo")
|
||||
.bearer_auth(TOKEN)
|
||||
.send()
|
||||
.await
|
||||
.is_err()
|
||||
|
@ -91,7 +93,7 @@ async fn auth() {
|
|||
client
|
||||
.post("http://127.0.0.1:8181/api/v3/write_lp?db=foo")
|
||||
.body("cpu,host=a val=1i 123")
|
||||
.bearer_auth("foo")
|
||||
.bearer_auth(TOKEN)
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
|
@ -101,7 +103,7 @@ async fn auth() {
|
|||
assert_eq!(
|
||||
client
|
||||
.get("http://127.0.0.1:8181/api/v3/query_sql?db=foo&q=select+*+from+cpu")
|
||||
.bearer_auth("foo")
|
||||
.bearer_auth(TOKEN)
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
|
@ -113,7 +115,7 @@ async fn auth() {
|
|||
assert_eq!(
|
||||
client
|
||||
.get("http://127.0.0.1:8181/api/v3/query_sql?db=foo&q=select+*+from+cpu")
|
||||
.header("Authorization", "Bearer foo whee")
|
||||
.header("Authorization", format!("Bearer {TOKEN} whee"))
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
|
@ -123,7 +125,7 @@ async fn auth() {
|
|||
assert_eq!(
|
||||
client
|
||||
.get("http://127.0.0.1:8181/api/v3/query_sql?db=foo&q=select+*+from+cpu")
|
||||
.header("Authorization", "bearer foo")
|
||||
.header("Authorization", format!("bearer {TOKEN}"))
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
|
@ -143,7 +145,7 @@ async fn auth() {
|
|||
assert_eq!(
|
||||
client
|
||||
.get("http://127.0.0.1:8181/api/v3/query_sql?db=foo&q=select+*+from+cpu")
|
||||
.header("Authorizon", "Bearer foo")
|
||||
.header("auth", format!("Bearer {TOKEN}"))
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
|
|
|
@ -38,6 +38,7 @@ arrow-flight.workspace = true
|
|||
arrow-json.workspace = true
|
||||
arrow-schema.workspace = true
|
||||
async-trait.workspace = true
|
||||
base64.workspace = true
|
||||
bytes.workspace = true
|
||||
chrono.workspace = true
|
||||
datafusion.workspace = true
|
||||
|
|
|
@ -30,7 +30,7 @@ use serde::de::DeserializeOwned;
|
|||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use sha2::Digest;
|
||||
use sha2::Sha256;
|
||||
use sha2::Sha512;
|
||||
use std::convert::Infallible;
|
||||
use std::fmt::Debug;
|
||||
use std::num::NonZeroI32;
|
||||
|
@ -516,7 +516,7 @@ where
|
|||
}
|
||||
|
||||
// Check that the hashed token is acceptable
|
||||
let authorized = &Sha256::digest(token)[..] == bearer_token;
|
||||
let authorized = &Sha512::digest(token)[..] == bearer_token;
|
||||
if !authorized {
|
||||
return Err(AuthorizationError::Unauthorized);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue