Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog

## 2.58.6
## Unreleased

### Fixes

- Do not combine a URL and non-embedded auth token from different configuration files. When configuration sources provide only one of these values, an existing value from another source may be ignored with a warning. Configure the URL and token in the same file or through CLI arguments and environment variables, which are treated as one runtime source. This change does not alter parent-config discovery or how other configuration keys are selected ([#3382](https://github.com/getsentry/sentry-cli/pull/3382)).

### Security Fixes

Expand Down
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class SentryCli {
*
* @param {string | null} [configFile] - Path to Sentry CLI config properties, as described in https://docs.sentry.io/learn/cli/configuration/#properties-files.
* By default, the config file is looked for upwards from the current path and defaults from ~/.sentryclirc are always loaded.
* A URL and a non-embedded auth token must be configured in the same file or through runtime options and environment variables.
* This value will update `SENTRY_PROPERTIES` env variable.
* @param {SentryCliOptions} [options] - More options to pass to the CLI
*/
Expand Down
20 changes: 11 additions & 9 deletions src/commands/login.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ pub fn make_command(command: Command) -> Command {
)
}

fn update_config(config: &Config, token: AuthToken) -> Result<()> {
fn update_config(config: &Config, token: AuthToken, url: &str) -> Result<()> {
let mut new_cfg = config.clone();
new_cfg.set_auth(Auth::Token(token));
new_cfg.set_auth_and_url(Auth::Token(token), url);
new_cfg.save()?;
Ok(())
}
Expand Down Expand Up @@ -61,7 +61,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
}

let mut token;
loop {
let validated_url = loop {
token = if let Some(token) = predefined_token {
token.to_owned()
} else {
Expand All @@ -72,6 +72,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
cfg.set_auth(Auth::Token(token.clone()));
Ok(())
})?;
let tested_url = test_cfg.get_base_url()?.to_owned();

match Api::with_config(test_cfg).authenticated()?.get_auth_info() {
Ok(info) => {
Expand All @@ -85,7 +86,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
println!("Valid org token");
}
}
break;
break tested_url;
}
Err(err) => {
// Convert to anyhow error to take advantage of anyhow's Debug impl
Expand All @@ -98,20 +99,21 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
}
}
}
}
};

let config_to_update = if matches.get_flag("global") {
Config::global()?
} else {
Config::from_cli_config()?
Config::from_cli_config(None, None, None)?
};

if should_warn_about_overwrite(config_to_update.get_auth(), &token) {
let persisted_auth = config_to_update.get_persisted_auth();
if should_warn_about_overwrite(persisted_auth.as_ref(), &token) {
println!();
println!("Warning: You are about to overwrite an existing token!");

// Show organization information
if let Some(existing_auth) = config_to_update.get_auth() {
if let Some(existing_auth) = persisted_auth.as_ref() {
let existing_org = get_org_from_auth(existing_auth);
let new_org = get_org_from_token(&token);

Expand All @@ -126,7 +128,7 @@ pub fn execute(matches: &ArgMatches) -> Result<()> {
}
}

update_config(&config_to_update, token)?;
update_config(&config_to_update, token, &validated_url)?;
println!();
println!(
"Stored token in {}",
Expand Down
28 changes: 6 additions & 22 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::process;
use std::{env, iter};

use crate::api::Api;
use crate::config::{Auth, Config};
use crate::config::Config;
use crate::constants::{ARCH, PLATFORM, VERSION};
use crate::utils::auth_token::{redact_token_from_string, AuthToken};
use crate::utils::logging::set_quiet_mode;
Expand Down Expand Up @@ -137,26 +137,6 @@ fn preexecute_hooks() -> Result<bool> {
}

fn configure_args(config: &mut Config, matches: &ArgMatches) {
if let Some(api_key) = matches.get_one::<String>("api_key") {
log::warn!(
"[DEPRECTATION NOTICE] API key authentication and the --api-key argument are \
deprecated. \
Please generate an auth token, and use the --auth-token argument instead."
);

#[expect(deprecated, reason = "Auth key is deprecated.")]
let auth = Auth::Key(api_key.to_owned());
config.set_auth(auth);
}

if let Some(auth_token) = matches.get_one::<AuthToken>("auth_token") {
config.set_auth(Auth::Token(auth_token.to_owned()));
}

if let Some(url) = matches.get_one::<String>("url") {
config.set_base_url(url);
}

if let Some(headers) = matches.get_many::<String>("headers") {
let headers = headers.map(|h| h.to_owned()).collect();
config.set_headers(headers);
Expand Down Expand Up @@ -280,7 +260,11 @@ pub fn execute() -> Result<()> {
if let Some(&log_level) = log_level {
set_max_level(log_level);
}
let mut config = Config::from_cli_config()?;
let mut config = Config::from_cli_config(
matches.get_one::<String>("url").map(String::as_str),
matches.get_one::<AuthToken>("auth_token"),
matches.get_one::<String>("api_key").map(String::as_str),
)?;
configure_args(&mut config, &matches);
set_quiet_mode(matches.get_flag("quiet"));

Expand Down
Loading
Loading