Skip to content

Commit 712e262

Browse files
authored
pushpin-publish: support bearer auth (#48315)
1 parent 18b6d07 commit 712e262

4 files changed

Lines changed: 43 additions & 69 deletions

File tree

Cargo.lock

Lines changed: 0 additions & 57 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ mio = { version = "1", features = ["os-poll", "os-ext", "net"] }
3939
notify = "7"
4040
openssl = "=0.10.72"
4141
paste = "1.0"
42-
rustls = { version = "0.23", features = ["ring"] }
42+
rustls = { version = "0.23", default-features = false, features = ["ring", "std", "tls12"] }
4343
rustls-native-certs = "0.6"
4444
serde = { version = "1.0", features = ["derive"] }
4545
serde_json = "1.0"

src/bin/pushpin-publish.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
22
* Copyright (C) 2021-2023 Fanout, Inc.
3+
* Copyright (C) 2026 Fastly, Inc.
34
*
45
* This file is part of Pushpin.
56
*
@@ -22,7 +23,7 @@
2223

2324
use clap::{Arg, ArgAction, Command};
2425
use pushpin::core::version;
25-
use pushpin::publish::{run, Action, Config, Content, Message};
26+
use pushpin::publish::{run, Action, AuthType, Config, Content, Message};
2627
use std::env;
2728
use std::error::Error;
2829
use std::process;
@@ -45,7 +46,7 @@ struct Args {
4546
no_seq: bool,
4647
no_eol: bool,
4748
spec: String,
48-
user: Option<String>,
49+
auth: Option<(AuthType, String)>,
4950
}
5051

5152
fn process_args_and_run(args: Args) -> Result<(), Box<dyn Error>> {
@@ -112,7 +113,7 @@ fn process_args_and_run(args: Args) -> Result<(), Box<dyn Error>> {
112113

113114
let config = Config {
114115
spec: args.spec,
115-
basic_auth: args.user,
116+
auth: args.auth,
116117
channel: args.channel,
117118
id: args.id,
118119
prev_id: args.prev_id,
@@ -242,6 +243,14 @@ fn main() {
242243
.value_name("user:pass")
243244
.help("Authenticate using basic auth"),
244245
)
246+
.arg(
247+
Arg::new("bearer")
248+
.short('B')
249+
.long("bearer")
250+
.num_args(1)
251+
.value_name("token")
252+
.help("Authenticate using bearer auth"),
253+
)
245254
.get_matches();
246255

247256
let channel = matches.get_one::<String>("channel").unwrap().clone();
@@ -289,6 +298,17 @@ fn main() {
289298
let spec = matches.get_one::<String>("spec").unwrap().clone();
290299

291300
let user = matches.get_one::<String>("user").cloned();
301+
let bearer = matches.get_one::<String>("bearer").cloned();
302+
303+
let auth = match (user, bearer) {
304+
(Some(_), Some(_)) => {
305+
eprintln!("Error: only one authentication method can be specified");
306+
process::exit(1);
307+
}
308+
(Some(user), None) => Some((AuthType::Basic, user)),
309+
(None, Some(bearer)) => Some((AuthType::Bearer, bearer)),
310+
(None, None) => None,
311+
};
292312

293313
let args = Args {
294314
channel,
@@ -305,7 +325,7 @@ fn main() {
305325
no_seq,
306326
no_eol,
307327
spec,
308-
user,
328+
auth,
309329
};
310330

311331
if let Err(e) = process_args_and_run(args) {

src/publish/mod.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -309,9 +309,15 @@ impl Write for Stream {
309309
}
310310
}
311311

312+
#[derive(Copy, Clone)]
313+
pub enum AuthType {
314+
Basic,
315+
Bearer,
316+
}
317+
312318
fn publish_http(
313319
base_url: &str,
314-
basic_auth: Option<&str>,
320+
auth: Option<(AuthType, &str)>,
315321
item: &serde_json::Value,
316322
) -> Result<(), Box<dyn Error>> {
317323
let parsed_url = match parse_url(base_url) {
@@ -340,12 +346,17 @@ fn publish_http(
340346
body.len()
341347
);
342348

343-
if let Some(s) = basic_auth {
349+
if let Some((auth_type, value)) = auth {
344350
if parsed_url.scheme != "https" {
345351
return Err("Authentication requires https".into());
346352
}
347353

348-
req.push_str(&format!("Authorization: Basic {}\r\n", base64::encode(s)));
354+
let header_value = match auth_type {
355+
AuthType::Basic => format!("Basic {}", base64::encode(value)),
356+
AuthType::Bearer => format!("Bearer {value}"),
357+
};
358+
359+
req.push_str(&format!("Authorization: {header_value}\r\n"));
349360
}
350361

351362
req += "\r\n";
@@ -391,7 +402,7 @@ fn publish_http(
391402

392403
let pos = match rest.find(' ') {
393404
Some(pos) => pos,
394-
None => return Err(io::Error::from(io::ErrorKind::InvalidData).into()),
405+
None => rest.len(),
395406
};
396407

397408
let code = &rest[..pos];
@@ -451,7 +462,7 @@ pub enum Action {
451462

452463
pub struct Config {
453464
pub spec: String,
454-
pub basic_auth: Option<String>,
465+
pub auth: Option<(AuthType, String)>,
455466
pub channel: String,
456467
pub id: String,
457468
pub prev_id: String,
@@ -609,9 +620,9 @@ pub fn run(config: &Config) -> Result<(), Box<dyn Error>> {
609620
if config.spec.starts_with("https:") || config.spec.starts_with("http:") {
610621
let item = tnet_to_json(&item)?;
611622

612-
let basic_auth = config.basic_auth.as_deref();
623+
let auth = config.auth.as_ref().map(|(t, v)| (*t, v.as_str()));
613624

614-
publish_http(&config.spec, basic_auth, &item)?;
625+
publish_http(&config.spec, auth, &item)?;
615626
} else {
616627
publish_zmq(&config.spec, &item)?;
617628
}

0 commit comments

Comments
 (0)