Skip to content

Commit 3db4c45

Browse files
chlowellheaths
andauthored
Replace DefaultAzureCredential with DeveloperToolsCredential (#2873)
DeveloperToolsCredential is effectively the DefaultAzureCredential from other SDKs, configured for dev mode. It's designed to simplify getting started with the SDK, for example by copying sample code. It only supports authenticating via dev tools such as `az` and `azd`, and its behavior isn't configurable. Developers who want to set additional options for its constituent types or change their order can instead use them directly. Similarly to DefaultAzureCredential, DeveloperToolsCredential requests a token from each dev tool in turn, stopping when one provides a token. After receiving a token from some tool, a DeveloperToolsCredential instance uses that tool exclusively; it never tries the others again. There are a couple big reasons for removing DefaultAzureCredential instead of implementing it as in other SDKs: - **Default**AzureCredential implies it's always a good choice, if not the only choice, when in fact it's typically better to use a more specific type - trying a sequence of credentials introduces uncertainty and can be dangerous (see #2283 and [guidance for other SDKs](https://aka.ms/azsdk/net/identity/credential-chains#usage-guidance-for-defaultazurecredential)) --------- Co-authored-by: Heath Stewart <[email protected]>
1 parent 189d374 commit 3db4c45

File tree

46 files changed

+493
-607
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+493
-607
lines changed

sdk/core/azure_core/README.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,12 @@ available directly on `ClientOptions`.
7272

7373
```rust no_run
7474
use azure_core::http::ClientOptions;
75-
use azure_identity::DefaultAzureCredential;
75+
use azure_identity::DeveloperToolsCredential;
7676
use azure_security_keyvault_secrets::{SecretClient, SecretClientOptions};
7777

7878
#[tokio::main]
7979
async fn main() -> Result<(), Box<dyn std::error::Error>> {
80-
let credential = DefaultAzureCredential::new()?;
80+
let credential = DeveloperToolsCredential::new(None)?;
8181

8282
let options = SecretClientOptions {
8383
api_version: "7.5".to_string(),
@@ -102,13 +102,13 @@ This type provides access to both the deserialized result of the service call, a
102102

103103
```rust no_run
104104
use azure_core::http::Response;
105-
use azure_identity::DefaultAzureCredential;
105+
use azure_identity::DeveloperToolsCredential;
106106
use azure_security_keyvault_secrets::{models::Secret, SecretClient};
107107

108108
#[tokio::main]
109109
async fn main() -> Result<(), Box<dyn std::error::Error>> {
110110
// create a client
111-
let credential = DefaultAzureCredential::new()?;
111+
let credential = DeveloperToolsCredential::new(None)?;
112112
let client = SecretClient::new(
113113
"https://<your-key-vault-name>.vault.azure.net/",
114114
credential.clone(),
@@ -146,13 +146,13 @@ When a service call fails, the returned `Result` will contain an `Error`. The `E
146146

147147
```rust no_run
148148
use azure_core::{error::{ErrorKind, HttpError}, http::{Response, StatusCode}};
149-
use azure_identity::DefaultAzureCredential;
149+
use azure_identity::DeveloperToolsCredential;
150150
use azure_security_keyvault_secrets::SecretClient;
151151

152152
#[tokio::main]
153153
async fn main() -> Result<(), Box<dyn std::error::Error>> {
154154
// create a client
155-
let credential = DefaultAzureCredential::new()?;
155+
let credential = DeveloperToolsCredential::new(None)?;
156156
let client = SecretClient::new(
157157
"https://<your-key-vault-name>.vault.azure.net/",
158158
credential.clone(),
@@ -183,14 +183,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
183183
If a service call returns multiple values in pages, it should return `Result<Pager<T>>` as a result. You can iterate all items from all pages.
184184

185185
```rust no_run
186-
use azure_identity::DefaultAzureCredential;
186+
use azure_identity::DeveloperToolsCredential;
187187
use azure_security_keyvault_secrets::{ResourceExt, SecretClient};
188188
use futures::TryStreamExt;
189189

190190
#[tokio::main]
191191
async fn main() -> Result<(), Box<dyn std::error::Error>> {
192192
// create a client
193-
let credential = DefaultAzureCredential::new()?;
193+
let credential = DeveloperToolsCredential::new(None)?;
194194
let client = SecretClient::new(
195195
"https://<your-key-vault-name>.vault.azure.net/",
196196
credential.clone(),
@@ -214,14 +214,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
214214
To instead iterate over all pages, call `into_pages()` on the returned `Pager`.
215215

216216
```rust no_run
217-
use azure_identity::DefaultAzureCredential;
217+
use azure_identity::DeveloperToolsCredential;
218218
use azure_security_keyvault_secrets::{ResourceExt, SecretClient};
219219
use futures::TryStreamExt;
220220

221221
#[tokio::main]
222222
async fn main() -> Result<(), Box<dyn std::error::Error>> {
223223
// create a client
224-
let credential = DefaultAzureCredential::new()?;
224+
let credential = DeveloperToolsCredential::new(None)?;
225225
let client = SecretClient::new(
226226
"https://<your-key-vault-name>.vault.azure.net/",
227227
credential.clone(),
@@ -252,7 +252,7 @@ If a service call may take a while to process, it should return `Result<Poller<T
252252
The `Poller<T>` implements `futures::Stream` so you can asynchronously iterate over each status monitor update:
253253

254254
```rust no_run
255-
use azure_identity::DefaultAzureCredential;
255+
use azure_identity::DeveloperToolsCredential;
256256
use azure_security_keyvault_certificates::{
257257
CertificateClient,
258258
models::{CreateCertificateParameters, CertificatePolicy, X509CertificateProperties, IssuerParameters},
@@ -261,7 +261,7 @@ use futures::stream::TryStreamExt as _;
261261

262262
#[tokio::main]
263263
async fn main() -> Result<(), Box<dyn std::error::Error>> {
264-
let credential = DefaultAzureCredential::new()?;
264+
let credential = DeveloperToolsCredential::new(None)?;
265265
let client = CertificateClient::new(
266266
"https://your-key-vault-name.vault.azure.net/",
267267
credential.clone(),
@@ -308,15 +308,15 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
308308
If you just want to wait until the `Poller<T>` is complete and get the last status monitor, you can await `wait()`:
309309

310310
```rust no_run
311-
use azure_identity::DefaultAzureCredential;
311+
use azure_identity::DeveloperToolsCredential;
312312
use azure_security_keyvault_certificates::{
313313
CertificateClient,
314314
models::{CreateCertificateParameters, CertificatePolicy, X509CertificateProperties, IssuerParameters},
315315
};
316316

317317
#[tokio::main]
318318
async fn main() -> Result<(), Box<dyn std::error::Error>> {
319-
let credential = DefaultAzureCredential::new()?;
319+
let credential = DeveloperToolsCredential::new(None)?;
320320
let client = CertificateClient::new(
321321
"https://your-key-vault-name.vault.azure.net/",
322322
credential.clone(),
@@ -398,13 +398,13 @@ There can only be one async runtime set in a given process, so attempts to set t
398398
To help protected end users from accidental Personally-Identifiable Information (PII) from leaking into logs or traces, models' default implementation of `core::fmt::Debug` formats as non-exhaustive structure tuple e.g.,
399399

400400
```rust no_run
401-
use azure_identity::DefaultAzureCredential;
401+
use azure_identity::DeveloperToolsCredential;
402402
use azure_security_keyvault_secrets::{ResourceExt, SecretClient};
403403

404404
#[tokio::main]
405405
async fn main() -> Result<(), Box<dyn std::error::Error>> {
406406
// create a client
407-
let credential = DefaultAzureCredential::new()?;
407+
let credential = DeveloperToolsCredential::new(None)?;
408408
let client = SecretClient::new(
409409
"https://<your-key-vault-name>.vault.azure.net/",
410410
credential.clone(),

sdk/core/azure_core/src/http/pager.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,13 +518,13 @@ impl<P> PageIterator<P> {
518518
/// that, when first iterated, will get the next page of results.
519519
///
520520
/// ``` no_run
521-
/// use azure_identity::DefaultAzureCredential;
521+
/// use azure_identity::DeveloperToolsCredential;
522522
/// use azure_security_keyvault_secrets::SecretClient;
523523
/// use futures::stream::TryStreamExt as _;
524524
///
525525
/// # #[tokio::main]
526526
/// # async fn main() -> azure_core::Result<()> {
527-
/// let client = SecretClient::new("https://my-vault.vault.azure.net", DefaultAzureCredential::new()?, None)?;
527+
/// let client = SecretClient::new("https://my-vault.vault.azure.net", DeveloperToolsCredential::new(None)?, None)?;
528528
///
529529
/// // Advance first pager to first page.
530530
/// let mut pager = client.list_secret_properties(None)?

sdk/core/azure_core_opentelemetry/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ It allows Rust applications which use the [OpenTelemetry](https://opentelemetry.
1111
To integrate the OpenTelemetry APIs with the Azure SDK for Rust, you create a `OpenTelemetryTracerProvider` and pass it into your SDK ClientOptions.
1212

1313
```rust no_run
14-
# use azure_identity::DefaultAzureCredential;
14+
# use azure_identity::DeveloperToolsCredential;
1515
# use azure_core::{http::{ClientOptions, RequestInstrumentationOptions}};
1616
# #[derive(Default)]
1717
# struct ServiceClientOptions {
@@ -44,7 +44,7 @@ let options = ServiceClientOptions {
4444
If it is more convenient to use the global OpenTelemetry provider, then the `OpenTelemetryTracerProvider::new_from_global_provider` method will configure the OpenTelemetry support to use the global provider instead of a custom configured provider.
4545

4646
```rust no_run
47-
# use azure_identity::DefaultAzureCredential;
47+
# use azure_identity::DeveloperToolsCredential;
4848
# use azure_core::{http::{ClientOptions, RequestInstrumentationOptions}};
4949

5050
# #[derive(Default)]

sdk/core/azure_core_test/src/credentials.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ use azure_core::{
66
credentials::{AccessToken, Secret, TokenCredential, TokenRequestOptions},
77
time::{Duration, OffsetDateTime},
88
};
9-
use azure_identity::{AzurePipelinesCredential, DefaultAzureCredential, TokenCredentialOptions};
9+
#[cfg(target_arch = "wasm32")]
10+
use azure_core::{error::ErrorKind, Error};
11+
#[cfg(not(target_arch = "wasm32"))]
12+
use azure_identity::DeveloperToolsCredential;
13+
use azure_identity::{AzurePipelinesCredential, TokenCredentialOptions};
1014
use std::{env, sync::Arc};
1115

1216
/// A mock [`TokenCredential`] useful for testing.
@@ -38,7 +42,7 @@ impl TokenCredential for MockCredential {
3842
/// Gets a `TokenCredential` appropriate for the current environment.
3943
///
4044
/// When running in Azure Pipelines, this will return an [`AzurePipelinesCredential`];
41-
/// otherwise, it will return a [`DefaultAzureCredential`].
45+
/// otherwise, it will return a [`DeveloperToolsCredential`].
4246
pub fn from_env(
4347
options: Option<TokenCredentialOptions>,
4448
) -> azure_core::Result<Arc<dyn TokenCredential>> {
@@ -65,9 +69,13 @@ pub fn from_env(
6569
)? as Arc<dyn TokenCredential>);
6670
}
6771
}
68-
69-
Ok(
70-
DefaultAzureCredential::with_options(options.unwrap_or_default())?
71-
as Arc<dyn TokenCredential>,
72-
)
72+
#[cfg(target_arch = "wasm32")]
73+
{
74+
Err(Error::message(
75+
ErrorKind::Other,
76+
"No local development credential for WASM.",
77+
))
78+
}
79+
#[cfg(not(target_arch = "wasm32"))]
80+
Ok(DeveloperToolsCredential::new(None)? as Arc<dyn TokenCredential>)
7381
}

sdk/core/azure_core_test/src/http/clients.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use std::fmt;
1919
/// Bytes,
2020
/// };
2121
/// use azure_core_test::http::MockHttpClient;
22-
/// use azure_identity::DefaultAzureCredential;
22+
/// use azure_identity::DeveloperToolsCredential;
2323
/// use azure_security_keyvault_secrets::{SecretClient, SecretClientOptions};
2424
/// use futures::FutureExt as _;
2525
/// use std::sync::Arc;
@@ -34,7 +34,7 @@ use std::fmt;
3434
/// Bytes::from_static(br#"{"value":"secret"}"#),
3535
/// ))
3636
/// }.boxed()));
37-
/// let credential = DefaultAzureCredential::new()?;
37+
/// let credential = DeveloperToolsCredential::new(None)?;
3838
/// let options = SecretClientOptions {
3939
/// client_options: ClientOptions {
4040
/// transport: Some(TransportOptions::new(mock_client.clone())),

sdk/core/azure_core_test/src/recording.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ impl Recording {
8888
match self.test_mode {
8989
TestMode::Playback => Arc::new(MockCredential) as Arc<dyn TokenCredential>,
9090
_ => credentials::from_env(None).map_or_else(
91-
|err| panic!("failed to create DefaultAzureCredential: {err}"),
91+
|err| panic!("failed to create DeveloperToolsCredential: {err}"),
9292
|cred| cred as Arc<dyn TokenCredential>,
9393
),
9494
}

sdk/cosmos/azure_data_cosmos/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,22 @@ In order to interact with the Azure Cosmos DB service, you'll need to create an
4646

4747
**Using Microsoft Entra ID**
4848

49-
The example shown below use a `DefaultAzureCredential`, which is appropriate for most local development environments. Additionally, we recommend using a managed identity for authentication in production environments. You can find more information on different ways of authenticating and their corresponding credential types in the [Azure Identity] documentation.
49+
The example shown below use a `DeveloperToolsCredential`, which is appropriate for most local development environments. Additionally, we recommend using a managed identity for authentication in production environments. You can find more information on different ways of authenticating and their corresponding credential types in the [Azure Identity] documentation.
5050

51-
The `DefaultAzureCredential` will automatically pick up on an Azure CLI authentication. Ensure you are logged in with the Azure CLI:
51+
The `DeveloperToolsCredential` will automatically pick up on an Azure CLI authentication. Ensure you are logged in with the Azure CLI:
5252

5353
```sh
5454
az login
5555
```
5656

57-
Instantiate a `DefaultAzureCredential` to pass to the client. The same instance of a token credential can be used with multiple clients if they will be authenticating with the same identity.
57+
Instantiate a `DeveloperToolsCredential` to pass to the client. The same instance of a token credential can be used with multiple clients if they will be authenticating with the same identity.
5858

5959
```rust
60-
use azure_identity::DefaultAzureCredential;
60+
use azure_identity::DeveloperToolsCredential;
6161
use azure_data_cosmos::CosmosClient;
6262

6363
async fn example() -> Result<(), Box<dyn std::error::Error>> {
64-
let credential = DefaultAzureCredential::new()?;
64+
let credential = DeveloperToolsCredential::new(None)?;
6565
let cosmos_client = CosmosClient::new("myAccountEndpointURL", credential.clone(), None)?;
6666
Ok(())
6767
}

sdk/cosmos/azure_data_cosmos/examples/cosmos/main.rs

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

44
use azure_data_cosmos::CosmosClient;
5-
use azure_identity::DefaultAzureCredential;
5+
use azure_identity::DeveloperToolsCredential;
66
use clap::{Args, CommandFactory, Parser, Subcommand};
77
use std::error::Error;
88

@@ -94,7 +94,7 @@ fn create_client(args: &SharedArgs) -> Result<CosmosClient, Box<dyn Error>> {
9494
Err("cannot authenticate with a key unless the 'key_auth' feature is enabled".into())
9595
}
9696
} else {
97-
let cred = DefaultAzureCredential::new().unwrap();
97+
let cred = DeveloperToolsCredential::new(None).unwrap();
9898
Ok(CosmosClient::new(&args.endpoint, cred, None)?)
9999
}
100100
}

sdk/cosmos/azure_data_cosmos/src/clients/cosmos_client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ impl CosmosClient {
4444
/// # use std::sync::Arc;
4545
/// use azure_data_cosmos::CosmosClient;
4646
///
47-
/// let credential = azure_identity::DefaultAzureCredential::new().unwrap();
47+
/// let credential = azure_identity::DeveloperToolsCredential::new(None).unwrap();
4848
/// let client = CosmosClient::new("https://myaccount.documents.azure.com/", credential, None).unwrap();
4949
/// ```
5050
pub fn new(

sdk/eventhubs/azure_messaging_eventhubs/README.md

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,20 @@ cargo add azure_identity tokio
5252

5353
In order to interact with the Azure Event Hubs service, you'll need to create an instance of the `ProducerClient` or the `ConsumerClient`. You need an **event hub namespace host URL** (which you may see as `serviceBusEndpoint` in the Azure CLI response when creating the Even Hubs Namespace), an **Event Hub name** (which you may see as `name` in the Azure CLI response when crating the Event Hub instance), and credentials to instantiate a client object.
5454

55-
The example shown below uses a [`DefaultAzureCredential`][default_cred_ref], which is appropriate for most local development environments. Additionally, we recommend using a managed identity for authentication in production environments. You can find more information on different ways of authenticating and their corresponding credential types in the [Azure Identity] documentation.
55+
The example shown below uses a `DeveloperToolsCredential`, which is appropriate for most local development environments. Additionally, we recommend using a managed identity for authentication in production environments. You can find more information on different ways of authenticating and their corresponding credential types in the [Azure Identity] documentation.
5656

57-
The `DefaultAzureCredential` will automatically pick up on an Azure CLI authentication. Ensure you are logged in with the Azure CLI:
57+
The `DeveloperToolsCredential` will automatically pick up on an Azure CLI authentication. Ensure you are logged in with the Azure CLI:
5858

5959
```azurecli
6060
az login
6161
```
6262

63-
Instantiate a `DefaultAzureCredential` to pass to the client. The same instance of a token credential can be used with multiple clients if they will be authenticating with the same identity.
63+
Instantiate a `DeveloperToolsCredential` to pass to the client. The same instance of a token credential can be used with multiple clients if they will be authenticating with the same identity.
6464

6565
### Create an Event Hubs message producer and send an event
6666

6767
```rust no_run
68-
use azure_identity::DefaultAzureCredential;
68+
use azure_identity::DeveloperToolsCredential;
6969
use azure_messaging_eventhubs::ProducerClient;
7070

7171
#[tokio::main]
@@ -74,7 +74,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
7474
let eventhub = "<EVENTHUB_NAME>";
7575

7676
// Create new credential
77-
let credential = DefaultAzureCredential::new()?;
77+
let credential = DeveloperToolsCredential::new(None)?;
7878

7979
// Create and open a new ProducerClient
8080
let producer = ProducerClient::builder()
@@ -125,14 +125,14 @@ Additional examples for various scenarios can be found on in the examples direct
125125

126126
```rust no_run
127127
use azure_core::Error;
128-
use azure_identity::DefaultAzureCredential;
128+
use azure_identity::DeveloperToolsCredential;
129129
use azure_messaging_eventhubs::ProducerClient;
130130

131131
async fn open_producer_client() -> Result<ProducerClient, Error> {
132132
let host = "<EVENTHUBS_HOST>";
133133
let eventhub = "<EVENTHUB_NAME>";
134134

135-
let credential = DefaultAzureCredential::new()?;
135+
let credential = DeveloperToolsCredential::new(None)?;
136136

137137
let producer = ProducerClient::builder()
138138
.open(host, eventhub, credential.clone())
@@ -183,14 +183,14 @@ async fn send_events(producer: &ProducerClient) -> Result<(), Error> {
183183

184184
```rust no_run
185185
use azure_core::Error;
186-
use azure_identity::DefaultAzureCredential;
186+
use azure_identity::DeveloperToolsCredential;
187187
use azure_messaging_eventhubs::ConsumerClient;
188188

189189
async fn open_consumer_client() -> Result<ConsumerClient, Error> {
190190
let host = "<EVENTHUBS_HOST>".to_string();
191191
let eventhub = "<EVENTHUB_NAME>".to_string();
192192

193-
let credential = DefaultAzureCredential::new()?;
193+
let credential = DeveloperToolsCredential::new(None)?;
194194

195195
let consumer = azure_messaging_eventhubs::ConsumerClient::builder()
196196
.open(&host, eventhub, credential.clone())
@@ -287,12 +287,11 @@ Azure SDK for Rust is licensed under the [MIT](https://github.com/Azure/azure-sd
287287
[API reference documentation]: https://docs.rs/azure_messaging_eventhubs/latest/azure_messaging_eventhubs
288288
[Azure CLI]: https://learn.microsoft.com/cli/azure
289289
[Azure subscription]: https://azure.microsoft.com/free/
290-
[Azure Identity]: https://github.com/Azure/azure-sdk-for-rust/tree/main/sdk/identity/azure_identity
290+
[Azure Identity]: https://aka.ms/azsdk/rust/identity/docs
291291
[Microsoft Open Source Code of Conduct]: https://opensource.microsoft.com/codeofconduct/
292292
[Product documentation]: https://learn.microsoft.com/azure/event-hubs/
293293
[Cargo]: https://crates.io/
294294
[Package (crates.io)]: https://crates.io/crates/azure_messaging_eventhubs
295295
[Source code]: https://github.com/Azure/azure-sdk-for-rust/tree/main/sdk/eventhubs/azure_messaging_eventhubs/src
296296
[CONTRIBUTING.md]: https://github.com/Azure/azure-sdk-for-rust/blob/main/CONTRIBUTING.md
297297
[Code of Conduct FAQ]: https://opensource.microsoft.com/codeofconduct/faq/
298-
[default_cred_ref]: https://docs.rs/azure_identity/latest/azure_identity/struct.DefaultAzureCredential.html

0 commit comments

Comments
 (0)