Skip to content

Commit 4d5ca1f

Browse files
authored
Remove azure_identity's old_azure_cli feature (#2443)
1 parent 4191b69 commit 4d5ca1f

File tree

6 files changed

+6
-208
lines changed

6 files changed

+6
-208
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,6 @@ tokio = { version = "1.0", default-features = false, features = [
126126
] }
127127
tracing = "0.1.40"
128128
tracing-subscriber = "0.3"
129-
tz-rs = { version = "0.6" }
130129
url = "2.2"
131130
uuid = { version = "1.0", features = ["v4"] }
132131
zerofrom = "0.1.5"

eng/dict/crates.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ typespec_client_core
6565
typespec_client_core
6666
typespec_macros
6767
typespec_macros
68-
tz-rs
6968
url
7069
uuid
7170
zerofrom

sdk/identity/azure_identity/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
- Removed `get_subscription()` and `get_tenant()` from `AzureCliCredential`.
1818
- `WorkloadIdentityCredential` constructors moved some parameters to an `Option<ClientAssertionCredentialOptions>` parameter.
1919
- Removed `clear_cache()` from all credential types
20+
- Removed `old_azure_cli` feature. `AzureCliCredential` now requires a recent version of the Azure CLI (2.54.0 or later).
2021
- Replaced `AppServiceManagedIdentityCredential`, `VirtualMachineManagedIdentityCredential`, and `ImdsId` with `ManagedIdentityCredential` and `UserAssignedId`
2122

2223
### Bugs Fixed

sdk/identity/azure_identity/Cargo.toml

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ tracing.workspace = true
2626
typespec_client_core = { workspace = true, features = ["derive"] }
2727
url.workspace = true
2828

29-
[target.'cfg(unix)'.dependencies]
30-
tz-rs = { workspace = true, optional = true }
31-
3229
[dev-dependencies]
3330
azure_core_test.workspace = true
3431
azure_security_keyvault_secrets = { path = "../../keyvault/azure_security_keyvault_secrets" }
@@ -40,19 +37,12 @@ tokio.workspace = true
4037
tracing-subscriber.workspace = true
4138

4239
[features]
43-
default = ["reqwest", "old_azure_cli"]
40+
default = ["reqwest"]
4441
reqwest = ["azure_core/reqwest"]
4542
reqwest_rustls = ["azure_core/reqwest_rustls"]
4643
tokio = ["azure_core/tokio"]
4744
client_certificate = ["openssl"]
4845

49-
# If you are using and Azure CLI version older than 2.54.0 from November 2023,
50-
# upgrade your Azure CLI version or enable this feature.
51-
# Azure CLI 2.54.0 and above has an "expires_on" timestamp that we can use.
52-
# https://github.com/Azure/azure-cli/releases/tag/azure-cli-2.54.0
53-
# https://github.com/Azure/azure-cli/issues/19700
54-
old_azure_cli = ["time/local-offset", "tz-rs"]
55-
5646
[lints]
5747
workspace = true
5848

sdk/identity/azure_identity/src/credentials/azure_cli_credentials.rs

Lines changed: 4 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -16,105 +16,11 @@ use std::{ffi::OsStr, fmt::Debug, str, sync::Arc};
1616
use time::OffsetDateTime;
1717
use tracing::trace;
1818

19-
#[cfg(feature = "old_azure_cli")]
20-
mod az_cli_date_format {
21-
use azure_core::error::{ErrorKind, ResultExt};
22-
use serde::{Deserialize, Deserializer};
23-
use time::format_description::FormatItem;
24-
use time::macros::format_description;
25-
#[cfg(not(unix))]
26-
use time::UtcOffset;
27-
use time::{OffsetDateTime, PrimitiveDateTime};
28-
29-
// cspell:ignore subsecond
30-
const FORMAT: &[FormatItem] =
31-
format_description!("[year]-[month]-[day] [hour]:[minute]:[second].[subsecond digits:6]");
32-
33-
pub fn parse(s: &str) -> azure_core::Result<OffsetDateTime> {
34-
// expiresOn from azure cli uses the local timezone and needs to be converted to UTC
35-
let dt = PrimitiveDateTime::parse(s, FORMAT)
36-
.with_context(ErrorKind::DataConversion, || {
37-
format!("unable to parse expiresOn '{s}")
38-
})?;
39-
Ok(assume_local(&dt))
40-
}
41-
42-
#[cfg(unix)]
43-
/// attempt to convert `PrimitiveDateTime` to `OffsetDate` using
44-
/// `tz::TimeZone`. If any part of the conversion fails, such as if no
45-
/// timezone can be found, then use use the value as UTC.
46-
pub(crate) fn assume_local(date: &PrimitiveDateTime) -> OffsetDateTime {
47-
let as_utc = date.assume_utc();
48-
49-
// try parsing the timezone from `TZ` environment variable. If that
50-
// fails, or the environment variable doesn't exist, try using
51-
// `TimeZone::local`. If that fails, then just return the UTC date.
52-
let Some(tz) = std::env::var("TZ")
53-
.ok()
54-
.and_then(|x| tz::TimeZone::from_posix_tz(&x).ok())
55-
.or_else(|| tz::TimeZone::local().ok())
56-
else {
57-
return as_utc;
58-
};
59-
60-
let as_unix = as_utc.unix_timestamp();
61-
62-
// if we can't find the local time type, just return the UTC date
63-
let Ok(local_time_type) = tz.find_local_time_type(as_unix) else {
64-
return as_utc;
65-
};
66-
67-
// if we can't convert the unix timestamp to a DateTime, just return the UTC date
68-
let date = as_utc.date();
69-
let time = as_utc.time();
70-
let Ok(date) = tz::DateTime::new(
71-
date.year(),
72-
u8::from(date.month()),
73-
date.day(),
74-
time.hour(),
75-
time.minute(),
76-
time.second(),
77-
time.nanosecond(),
78-
*local_time_type,
79-
) else {
80-
return as_utc;
81-
};
82-
83-
// if we can't then convert to unix time (with the timezone) and then
84-
// back into an OffsetDateTime, then return the UTC date
85-
let Ok(date) = OffsetDateTime::from_unix_timestamp(date.unix_time()) else {
86-
return as_utc;
87-
};
88-
89-
date
90-
}
91-
92-
/// Assumes the local offset. Default to UTC if unable to get local offset.
93-
#[cfg(not(unix))]
94-
pub(crate) fn assume_local(date: &PrimitiveDateTime) -> OffsetDateTime {
95-
date.assume_offset(UtcOffset::current_local_offset().unwrap_or(UtcOffset::UTC))
96-
}
97-
98-
pub fn deserialize<'de, D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
99-
where
100-
D: Deserializer<'de>,
101-
{
102-
let s = String::deserialize(deserializer)?;
103-
parse(&s).map_err(serde::de::Error::custom)
104-
}
105-
}
106-
10719
/// The response from `az account get-access-token --output json`.
10820
#[derive(Debug, Clone, Deserialize)]
10921
struct CliTokenResponse {
11022
#[serde(rename = "accessToken")]
11123
pub access_token: Secret,
112-
#[cfg(feature = "old_azure_cli")]
113-
#[serde(rename = "expiresOn", with = "az_cli_date_format")]
114-
/// The token's expiry time formatted in the local timezone.
115-
/// Unfortunately, this requires additional timezone dependencies.
116-
/// See https://github.com/Azure/azure-cli/issues/19700 for details.
117-
pub local_expires_on: OffsetDateTime,
11824
#[serde(rename = "expires_on")]
11925
/// The token's expiry time in seconds since the epoch, a unix timestamp.
12026
/// Available in Azure CLI 2.54.0 or newer.
@@ -131,19 +37,10 @@ impl CliTokenResponse {
13137
.with_context(ErrorKind::DataConversion, || {
13238
format!("unable to parse expires_on '{timestamp}'")
13339
})?),
134-
None => {
135-
#[cfg(feature = "old_azure_cli")]
136-
{
137-
Ok(self.local_expires_on)
138-
}
139-
#[cfg(not(feature = "old_azure_cli"))]
140-
{
141-
Err(Error::message(
142-
ErrorKind::DataConversion,
143-
"expires_on field not found. Please use Azure CLI 2.54.0 or newer.",
144-
))
145-
}
146-
}
40+
None => Err(Error::message(
41+
ErrorKind::DataConversion,
42+
"expires_on field not found. Please use Azure CLI 2.54.0 or newer.",
43+
)),
14744
}
14845
}
14946
}
@@ -307,68 +204,7 @@ impl From<TokenCredentialOptions> for AzureCliCredentialOptions {
307204
#[cfg(test)]
308205
mod tests {
309206
use super::*;
310-
#[cfg(feature = "old_azure_cli")]
311-
use serial_test::serial;
312-
#[cfg(feature = "old_azure_cli")]
313-
use time::macros::datetime;
314-
315-
#[cfg(feature = "old_azure_cli")]
316-
#[test]
317-
#[serial]
318-
fn can_parse_expires_on() -> azure_core::Result<()> {
319-
let expires_on = "2022-07-30 12:12:53.919110";
320-
assert_eq!(
321-
az_cli_date_format::parse(expires_on)?,
322-
az_cli_date_format::assume_local(&datetime!(2022-07-30 12:12:53.919110))
323-
);
324-
325-
Ok(())
326-
}
327-
328-
#[cfg(all(feature = "old_azure_cli", unix))]
329-
#[test]
330-
#[serial]
331-
/// test the timezone conversion works as expected on unix platforms
332-
///
333-
/// To validate the timezone conversion works as expected, this test
334-
/// temporarily sets the timezone to PST, performs the check, then resets
335-
/// the TZ environment variable.
336-
fn check_timezone() -> azure_core::Result<()> {
337-
let before = std::env::var("TZ").ok();
338-
std::env::set_var("TZ", "US/Pacific");
339-
let expires_on = "2022-11-30 12:12:53.919110";
340-
let result = az_cli_date_format::parse(expires_on);
341-
342-
if let Some(before) = before {
343-
std::env::set_var("TZ", before);
344-
} else {
345-
std::env::remove_var("TZ");
346-
}
347-
348-
let expected = datetime!(2022-11-30 20:12:53.0).assume_utc();
349-
assert_eq!(expected, result?);
350-
351-
Ok(())
352-
}
353-
354-
/// Test `from_json` for `CliTokenResponse` for old Azure CLI
355-
#[test]
356-
fn read_old_cli_token_response() -> azure_core::Result<()> {
357-
let json = br#"
358-
{
359-
"accessToken": "MuchLonger_NotTheRealOne_Sv8Orn0Wq0OaXuQEg",
360-
"expiresOn": "2024-01-01 19:23:16.000000",
361-
"subscription": "33b83be5-faf7-42ea-a712-320a5f9dd111",
362-
"tenant": "065e9f5e-870d-4ed1-af2b-1b58092353f3",
363-
"tokenType": "Bearer"
364-
}
365-
"#;
366-
let token_response: CliTokenResponse = from_json(json)?;
367-
assert_eq!(token_response.expires_on, None);
368-
Ok(())
369-
}
370207

371-
/// Test `from_json` for `CliTokenResponse` for current Azure CLI
372208
#[test]
373209
fn read_cli_token_response() -> azure_core::Result<()> {
374210
let json = br#"

0 commit comments

Comments
 (0)