Conversation
Signed-off-by: Jed Laundry <jlaundry@jlaundry.com>
|
Thank you for your contribution @jlaundry! We will review the pull request and get back to you soon. |
|
@chlowell can you take a look? |
chlowell
left a comment
There was a problem hiding this comment.
Allowing http://localhost as the base URL for Entra ID is weird and scary because that's definitely not the base URL for Entra ID. I recommend instead following the SDK's approach for testing credentials against a fake Entra: implement azure_core::http::HttpClient for some type to return programmatically defined responses instead of sending HTTP requests i.e., move your mock in-proc. See for example ClientSecretCredential tests and implementation of MockSts. If you prefer the external server approach, you could use a mock transport to send your credential's outgoing requests to that server, or a pipeline policy to change those requests' URLs.
You're right, that would work for what I wrote in the description, but I pressed Enter too quickly:
I'm also considering integration test cases where we want to run the test suite on developer laptops. In my case this is a mock Log Analytics API, but In these cases, I don't need a token from Entra ID, I just need a token that the mock service will accept. Unless I'm missing something, the options I can see for these integration test cases are (sorted by badness asc):
|
Naively--please let me know if I'm missing some detail--this seems straightforwardly achievable with the current API. If the mock service accepts a hardcoded token, you can provide that to your client via a mock credential (for example). If you want to exercise your real credential, you can give it a mock transport that returns responses containing the token (for example). If it's necessary or convenient to acquire tokens from a local server, you can use middleware in your credential's HTTP pipeline to redirect token requests to that server: #[derive(Debug, Clone)]
struct UrlReplacingPolicy {
url: Url,
}
impl UrlReplacingPolicy {
fn new(url: azure_core::http::Url) -> Self {
Self { url }
}
}
#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
impl azure_core::http::policies::Policy for UrlReplacingPolicy {
async fn send(
&self,
ctx: &azure_core::http::Context,
request: &mut azure_core::http::Request,
next: &[Arc<dyn azure_core::http::policies::Policy>],
) -> azure_core::http::policies::PolicyResult {
*request.url_mut() = self.url.clone();
next[0].send(ctx, request, &next[1..]).await
}
}
// usage looks like this for any type that sends HTTP requests
// directly i.e., not Azure[Developer]CliCredential
let credential = azure_identity::ClientSecretCredential::new(
"tenant ID",
"client ID".into(),
"secret".into(),
Some(azure_identity::ClientSecretCredentialOptions {
client_options: azure_core::http::options::ClientOptions {
per_call_policies: vec![Arc::new(UrlReplacingPolicy::new(
azure_core::http::Url::parse("http://localhost")?,
))],
..Default::default()
},
}),
)?; |
Thank you - I had completely missed that this was possible, and I've just tried it, and your example works well (for all the cases I can think of anyway)! I'm going to close this PR, but it may be useful for others to have this example; would it be useful if I raised a second PR with either example code and/or updated README? |
|
🤔 I imagine it would be helpful to point out that applications can write their own Policy (middleware) to run arbitrary code on requests and responses. We document that in the azure_core readme (for example) because every HTTP-based client in the SDK has the same API for it, however I doubt typical devs will think to search azure_core docs for a solution to a problem they face using a client crate. Do you think you would have connected the dots if there had been a note in the azure_identity readme about customizing HTTP pipelines with a link to the azure_core docs? |
Since
azure_identity0.28, only HTTPS authority endpoints have been allowed. This creates a problem when unit testing, for example, when we want to test our own SpecificAzureCredential implementation.This PR simply allows HTTP authority endpoints when the host address is localhost.