diff --git a/CHANGELOG.md b/CHANGELOG.md index d297ab90d3..70d8dfdada 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Fixes + +- (auth) Use an org auth token's embedded `region_url` as the API base URL so uploads from orgs with non-default (e.g. EU) data residency reach the correct region instead of failing with `Invalid org token`. Previously only the token's `url` (always the primary US URL) was honored, and `SENTRY_URL`/`--url` overrides were ignored ([#3377](https://github.com/getsentry/sentry-cli/pull/3377)) + ## 3.6.2 ### Fixes diff --git a/src/config.rs b/src/config.rs index a12b6cf57b..b3546d07b8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -150,7 +150,7 @@ impl Config { }; let token_url = token_data .as_ref() - .map(|data| data.url.as_str()) + .map(|data| data.base_url()) .unwrap_or_default(); let base_url = if token_url.is_empty() { auth_and_url.url.unwrap_or_else(|| DEFAULT_URL.to_owned()) @@ -282,7 +282,7 @@ impl Config { Some(Auth::Token(ref val)) => { self.cached_token_data = val.payload().cloned(); - if let Some(token_url) = self.cached_token_data.as_ref().map(|td| td.url.as_str()) { + if let Some(token_url) = self.cached_token_data.as_ref().map(|td| td.base_url()) { self.cached_base_url = token_url.to_owned(); } @@ -719,7 +719,9 @@ impl AuthAndUrl { /// Returns whether a token is self-contained because it has a nonempty embedded URL. fn token_has_embedded_url(token: &AuthToken) -> bool { - token.payload().is_some_and(|data| !data.url.is_empty()) + token + .payload() + .is_some_and(|data| !data.base_url().is_empty()) } /// Determines which inherited value must be removed before applying another source. diff --git a/src/utils/auth_token/org_auth_token.rs b/src/utils/auth_token/org_auth_token.rs index c464a2d0cf..97b8085a82 100644 --- a/src/utils/auth_token/org_auth_token.rs +++ b/src/utils/auth_token/org_auth_token.rs @@ -19,6 +19,19 @@ pub struct AuthTokenPayload { // URL may be missing from some old auth tokens, see getsentry/sentry#57123 #[serde(deserialize_with = "url_deserializer")] pub url: String, + + #[serde(default, deserialize_with = "url_deserializer")] + pub region_url: String, +} + +impl AuthTokenPayload { + pub fn base_url(&self) -> &str { + if self.region_url.is_empty() { + &self.url + } else { + &self.region_url + } + } } /// Deserializes a URL from a string, returning an empty string if the URL is missing or null. diff --git a/src/utils/auth_token/test.rs b/src/utils/auth_token/test.rs index a25568b150..d4bf1296fa 100644 --- a/src/utils/auth_token/test.rs +++ b/src/utils/auth_token/test.rs @@ -21,6 +21,8 @@ fn test_valid_org_auth_token() { let payload = token.payload().unwrap(); assert_eq!(payload.org, "sentry"); assert_eq!(payload.url, "http://localhost:8000"); + assert_eq!(payload.region_url, "http://localhost:8000"); + assert_eq!(payload.base_url(), "http://localhost:8000"); assert_eq!(good_token, token.raw().expose_secret().clone()); @@ -43,6 +45,8 @@ fn test_valid_org_auth_token_missing_url() { let payload = token.payload().unwrap(); assert_eq!(payload.org, "sentry"); assert!(payload.url.is_empty()); + assert_eq!(payload.region_url, "http://localhost:8000"); + assert_eq!(payload.base_url(), "http://localhost:8000"); assert_eq!(good_token, token.raw().expose_secret().clone()); diff --git a/tests/integration/_cases/org_tokens/url-mismatch-empty-token.trycmd b/tests/integration/_cases/org_tokens/url-mismatch-empty-token.trycmd index db83846b6c..961a68c8ed 100644 --- a/tests/integration/_cases/org_tokens/url-mismatch-empty-token.trycmd +++ b/tests/integration/_cases/org_tokens/url-mismatch-empty-token.trycmd @@ -1,8 +1,8 @@ -This auth token has an empty URL. We expect the --url argument to take precedence here +This auth token has an empty URL but a set region URL. The region URL is used as the base URL and takes precedence over the --url argument. ``` $ sentry-cli --auth-token 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 --url https://sentry.example.com info ? failed -Sentry Server: https://sentry.example.com +[..]WARN[..] Using http://localhost:8000 (embedded in token) rather than manually-configured URL https://sentry.example.com. To use https://sentry.example.com, please provide an auth token for https://sentry.example.com. ... ```