Skip to content

Commit 86c31c4

Browse files
chlowellheaths
andauthored
Credentials use azure_core Pipelines (#2986)
This entails significant supporting changes: - removed the mostly vestigial TokenCredentialOptions - ClientOptions now configures a credential's HttpClient - authority_host now comes from credential options; this is an interim replacement pending #2439 - tests which used this to mock env vars now do so via a test-only option - Added TokenRequestOptions.ClientMethodOptions (and the necessary lifetime parameter) so get_token can propagate the caller's Context - Added an optional ClientMethodOptions argument to `ClientAssertion::secret()` - this could instead be an optional Context but ClientMethodOptions seems more future-proof Closes #2436 --------- Co-authored-by: Heath Stewart <[email protected]>
1 parent 97b0f1e commit 86c31c4

31 files changed

+359
-380
lines changed

sdk/core/azure_core/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
- Added `RawResponse` to `ErrorKind::HttpResponse` that contains the HTTP status code, headers, and complete error response body.
88
- Added `RequestContent::from_slice()`.
9+
- Added `TokenRequestOptions { method_options: ClientMethodOptions }`.
910
- Added `TryFrom<T> for RequestContent<T, JsonFormat>` for JSON primitives.
1011
- Added support for WASM to the `async_runtime` module.
1112
- Added logging policy to log HTTP requests and responses in the pipeline. As a part of this change, sanitization support was added to places which log HTTP headers and URLs. The `azure_core::http::ClientOptions` has been enhanced with a `LoggingOptions` which allows a user/service client to specify headers or URL query parameters which should be allowed. Note that the sanitization feature is disabled if you build with the `debug` feature enabled.
@@ -14,6 +15,7 @@
1415

1516
### Breaking Changes
1617

18+
- Added a lifetime parameter to `TokenRequestOptions`.
1719
- Added the ability to configure pipeline configuration independently from `ClientOptions`. This adds a new optional `PipelineOptions` parameter to `azure_core::http::Pipeline::new()`. If not specified, it defaults to the expected options for `azure_core` services.
1820
- Changed `FromStr for RequestContent<T, F>` to `RequestContent::from_str()`.
1921
- Changed `TryFrom<&'static str> for RequestContent<T, F>` to `RequestContent::from_static()`.

sdk/core/azure_core/src/credentials.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
use serde::{Deserialize, Serialize};
77
use std::{borrow::Cow, fmt::Debug};
8-
use typespec_client_core::{fmt::SafeDebug, time::OffsetDateTime};
8+
use typespec_client_core::{fmt::SafeDebug, http::ClientMethodOptions, time::OffsetDateTime};
99

1010
/// Default Azure authorization scope.
1111
pub static DEFAULT_SCOPE_SUFFIX: &str = "/.default";
@@ -89,7 +89,9 @@ impl AccessToken {
8989

9090
/// Options for getting a token from a [`TokenCredential`]
9191
#[derive(Clone, Default, SafeDebug)]
92-
pub struct TokenRequestOptions;
92+
pub struct TokenRequestOptions<'a> {
93+
pub method_options: ClientMethodOptions<'a>,
94+
}
9395

9496
/// Represents a credential capable of providing an OAuth token.
9597
#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
@@ -99,6 +101,6 @@ pub trait TokenCredential: Send + Sync + Debug {
99101
async fn get_token(
100102
&self,
101103
scopes: &[&str],
102-
options: Option<TokenRequestOptions>,
104+
options: Option<TokenRequestOptions<'_>>,
103105
) -> crate::Result<AccessToken>;
104106
}

sdk/core/azure_core/src/http/policies/bearer_token_policy.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Licensed under the MIT License.
33

44
use crate::{
5-
credentials::{AccessToken, TokenCredential},
5+
credentials::{AccessToken, TokenCredential, TokenRequestOptions},
66
error::{Error, ErrorKind},
77
http::{
88
headers::AUTHORIZATION,
@@ -12,7 +12,7 @@ use crate::{
1212
use async_lock::RwLock;
1313
use async_trait::async_trait;
1414
use std::sync::Arc;
15-
use typespec_client_core::http::{Context, Request};
15+
use typespec_client_core::http::{ClientMethodOptions, Context, Request};
1616
use typespec_client_core::time::{Duration, OffsetDateTime};
1717

1818
/// Authentication policy for a bearer token.
@@ -66,7 +66,16 @@ impl Policy for BearerTokenCredentialPolicy {
6666
drop(access_token);
6767
let mut access_token = self.access_token.write().await;
6868
if access_token.is_none() {
69-
*access_token = Some(self.credential.get_token(&self.scopes(), None).await?);
69+
let options = TokenRequestOptions {
70+
method_options: ClientMethodOptions {
71+
context: ctx.clone(),
72+
},
73+
};
74+
*access_token = Some(
75+
self.credential
76+
.get_token(&self.scopes(), Some(options))
77+
.await?,
78+
);
7079
}
7180
}
7281
Some(token) if should_refresh(&token.expires_on) => {
@@ -78,7 +87,16 @@ impl Policy for BearerTokenCredentialPolicy {
7887
// access_token shouldn't be None here, but check anyway to guarantee unwrap won't panic
7988
if access_token.is_none() || access_token.as_ref().unwrap().expires_on == expires_on
8089
{
81-
match self.credential.get_token(&self.scopes(), None).await {
90+
let options = TokenRequestOptions {
91+
method_options: ClientMethodOptions {
92+
context: ctx.clone(),
93+
},
94+
};
95+
match self
96+
.credential
97+
.get_token(&self.scopes(), Some(options))
98+
.await
99+
{
82100
Ok(new_token) => {
83101
*access_token = Some(new_token);
84102
}
@@ -176,7 +194,7 @@ mod tests {
176194
async fn get_token(
177195
&self,
178196
_: &[&str],
179-
_: Option<TokenRequestOptions>,
197+
_: Option<TokenRequestOptions<'_>>,
180198
) -> Result<AccessToken> {
181199
let i = self.calls.fetch_add(1, Ordering::SeqCst);
182200
self.tokens

sdk/core/azure_core_test/src/credentials.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
//! Credentials for live and recorded tests.
55
use azure_core::{
66
credentials::{AccessToken, Secret, TokenCredential, TokenRequestOptions},
7+
http::ClientOptions,
78
time::{Duration, OffsetDateTime},
89
};
910
#[cfg(target_arch = "wasm32")]
1011
use azure_core::{error::ErrorKind, Error};
1112
#[cfg(not(target_arch = "wasm32"))]
1213
use azure_identity::DeveloperToolsCredential;
13-
use azure_identity::{AzurePipelinesCredential, TokenCredentialOptions};
14+
use azure_identity::{
15+
AzurePipelinesCredential, AzurePipelinesCredentialOptions, ClientAssertionCredentialOptions,
16+
};
1417
use std::{env, sync::Arc};
1518

1619
/// A mock [`TokenCredential`] useful for testing.
@@ -30,7 +33,7 @@ impl TokenCredential for MockCredential {
3033
async fn get_token(
3134
&self,
3235
scopes: &[&str],
33-
_: Option<TokenRequestOptions>,
36+
_: Option<TokenRequestOptions<'_>>,
3437
) -> azure_core::Result<AccessToken> {
3538
let token: Secret = format!("TEST TOKEN {}", scopes.join(" ")).into();
3639
let expires_on = OffsetDateTime::now_utc().saturating_add(Duration::minutes(5));
@@ -43,9 +46,7 @@ impl TokenCredential for MockCredential {
4346
///
4447
/// When running in Azure Pipelines, this will return an [`AzurePipelinesCredential`];
4548
/// otherwise, it will return a [`DeveloperToolsCredential`].
46-
pub fn from_env(
47-
options: Option<TokenCredentialOptions>,
48-
) -> azure_core::Result<Arc<dyn TokenCredential>> {
49+
pub fn from_env(options: Option<ClientOptions>) -> azure_core::Result<Arc<dyn TokenCredential>> {
4950
// cspell:ignore accesstoken azuresubscription
5051
let tenant_id = env::var("AZURESUBSCRIPTION_TENANT_ID").ok();
5152
let client_id = env::var("AZURESUBSCRIPTION_CLIENT_ID").ok();
@@ -65,7 +66,12 @@ pub fn from_env(
6566
client_id,
6667
&connection_id,
6768
access_token,
68-
options.map(Into::into),
69+
Some(AzurePipelinesCredentialOptions {
70+
credential_options: ClientAssertionCredentialOptions {
71+
client_options: options.unwrap_or_default(),
72+
..Default::default()
73+
},
74+
}),
6975
)? as Arc<dyn TokenCredential>);
7076
}
7177
}

sdk/cosmos/azure_data_cosmos/src/pipeline/authorization_policy.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ mod tests {
170170
async fn get_token(
171171
&self,
172172
scopes: &[&str],
173-
_: Option<TokenRequestOptions>,
173+
_: Option<TokenRequestOptions<'_>>,
174174
) -> azure_core::Result<AccessToken> {
175175
let token = format!("{}+{}", self.0, scopes.join(","));
176176
Ok(AccessToken::new(

sdk/eventhubs/azure_messaging_eventhubs/src/common/authorizer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ mod tests {
412412
async fn get_token(
413413
&self,
414414
_scopes: &[&str],
415-
_options: Option<TokenRequestOptions>,
415+
_options: Option<TokenRequestOptions<'_>>,
416416
) -> Result<AccessToken> {
417417
// Simulate a token refresh by incrementing the token get count
418418
// and updating the token expiration time

sdk/eventhubs/azure_messaging_eventhubs/src/consumer/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ and manage the lifecycle of the consumer client.
1010
### Creating a new [`ConsumerClient`] instance
1111

1212
```rust no_run
13-
use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
13+
use azure_identity::DeveloperToolsCredential;
1414
use azure_messaging_eventhubs::ConsumerClient;
1515

1616
#[tokio::main]
@@ -26,7 +26,7 @@ async fn main() -> Result<(), azure_core::Error> {
2626
### Opening a connection to the Event Hub
2727

2828
```rust no_run
29-
use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
29+
use azure_identity::DeveloperToolsCredential;
3030
use azure_messaging_eventhubs::ConsumerClient;
3131

3232
#[tokio::main]
@@ -53,7 +53,7 @@ async fn main() -> Result<(), azure_core::Error> {
5353
### Closing the connection to the Event Hub
5454

5555
```rust no_run
56-
use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
56+
use azure_identity::DeveloperToolsCredential;
5757
use azure_messaging_eventhubs::ConsumerClient;
5858

5959
#[tokio::main]
@@ -83,7 +83,7 @@ async fn main() -> Result<(), azure_core::Error> {
8383

8484
```rust no_run
8585
use futures::stream::StreamExt;
86-
use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
86+
use azure_identity::DeveloperToolsCredential;
8787
use azure_messaging_eventhubs::ConsumerClient;
8888
use futures::pin_mut;
8989

sdk/eventhubs/azure_messaging_eventhubs/src/consumer/event_receiver.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use tracing::trace;
1919
///
2020
/// ```no_run
2121
/// use azure_messaging_eventhubs::ConsumerClient;
22-
/// use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
22+
/// use azure_identity::DeveloperToolsCredential;
2323
/// use futures::stream::StreamExt;
2424
///
2525
/// #[tokio::main]

sdk/eventhubs/azure_messaging_eventhubs/src/consumer/mod.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ impl ConsumerClient {
6666
/// # #[tokio::main]
6767
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
6868
/// use azure_messaging_eventhubs::ConsumerClient;
69-
/// use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
69+
/// use azure_identity::DeveloperToolsCredential;
7070
///
7171
/// let my_credential = DeveloperToolsCredential::new(None)?;
7272
/// let consumer = ConsumerClient::builder()
@@ -124,7 +124,7 @@ impl ConsumerClient {
124124
///
125125
/// ``` no_run
126126
/// use azure_messaging_eventhubs::ConsumerClient;
127-
/// use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
127+
/// use azure_identity::DeveloperToolsCredential;
128128
///
129129
/// #[tokio::main]
130130
/// async fn main() {
@@ -199,7 +199,7 @@ impl ConsumerClient {
199199
///
200200
/// ```no_run
201201
/// use azure_messaging_eventhubs::ConsumerClient;
202-
/// use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
202+
/// use azure_identity::DeveloperToolsCredential;
203203
/// use futures::stream::StreamExt;
204204
///
205205
/// #[tokio::main]
@@ -301,7 +301,7 @@ impl ConsumerClient {
301301
///
302302
/// ``` no_run
303303
/// use azure_messaging_eventhubs::ConsumerClient;
304-
/// use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
304+
/// use azure_identity::DeveloperToolsCredential;
305305
///
306306
/// #[tokio::main]
307307
/// async fn main(){
@@ -347,7 +347,7 @@ impl ConsumerClient {
347347
///
348348
/// ``` no_run
349349
/// use azure_messaging_eventhubs::ConsumerClient;
350-
/// use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
350+
/// use azure_identity::DeveloperToolsCredential;
351351
///
352352
/// #[tokio::main]
353353
/// async fn main() {
@@ -548,7 +548,7 @@ pub mod builders {
548548
///
549549
/// ```no_run
550550
/// use azure_messaging_eventhubs::ConsumerClient;
551-
/// use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
551+
/// use azure_identity::DeveloperToolsCredential;
552552
///
553553
/// #[tokio::main]
554554
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -591,7 +591,7 @@ pub mod builders {
591591
///
592592
/// ```no_run
593593
/// use azure_messaging_eventhubs::ConsumerClient;
594-
/// use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
594+
/// use azure_identity::DeveloperToolsCredential;
595595
///
596596
/// #[tokio::main]
597597
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -651,7 +651,7 @@ pub mod builders {
651651
///
652652
/// ```
653653
/// use azure_messaging_eventhubs::ConsumerClient;
654-
/// use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
654+
/// use azure_identity::DeveloperToolsCredential;
655655
///
656656
/// #[tokio::main]
657657
/// async fn main() -> Result<(), Box<dyn std::error::Error>> {

sdk/eventhubs/azure_messaging_eventhubs/src/models/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use std::time::SystemTime;
4949
/// Basic usage:
5050
///
5151
/// ```no_run
52-
/// # use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
52+
/// # use azure_identity::DeveloperToolsCredential;
5353
/// # #[tokio::main]
5454
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
5555
/// # let my_credentials = DeveloperToolsCredential::new(None)?;
@@ -95,7 +95,7 @@ pub struct EventHubProperties {
9595
/// Basic usage:
9696
///
9797
/// ```no_run
98-
/// # use azure_identity::{DeveloperToolsCredential, TokenCredentialOptions};
98+
/// # use azure_identity::DeveloperToolsCredential;
9999
/// # #[tokio::main]
100100
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
101101
/// # let my_credentials = DeveloperToolsCredential::new(None)?;

0 commit comments

Comments
 (0)