Azure / azure-sdk-for-rust

This repository is for active development of the *unofficial* Azure SDK for Rust. This repository is *not* supported by the Azure SDK team.
MIT License
696 stars 241 forks source link

Redundant auth in IMDS client #1573

Open andlr opened 8 months ago

andlr commented 8 months ago

azure_svc_imds::Client can be created either with azure_svc_imds::Client::builder(credential).build()? or azure_svc_imds::Client:: new(endpoint, credential, scopes, options). In both cases, it requires a parameter of type Arc<dyn TokenCredential>.

I've tried to use it with DefaultAzureCredentialBuilder like this:

let credential = Arc::new(DefaultAzureCredentialBuilder::new().build());
let client = azure_svc_imds::Client::builder(credential).build()?;
let instance = self
    .client
    .instances_client()
    .get_metadata("true".to_owned())
    .await?;

And on Azure VM I got this error:

Error: AzureSdkError { source: Error { context: Message { kind: Credential, message: "Multiple errors were encountered while attempting to authenticate:\nenvironment credential - missing tenant id set in AZURE_TENANT_ID environment variable - environment variable not found\nIMDS - the requested identity has not been assigned to this resource\naz-cli - 'az account get-access-token' command failed: ERROR: AADSTS500011: The resource principal named http://169.254.169.254/ was not found in the tenant named elastio.com. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant. Trace ID: d03b54dd-6b84-4c25-8615-829c89873900 Correlation ID: 9250eada-3038-4305-94b9-b5fa20311d4d Timestamp: 2024-01-12 18:03:05Z\nInteractive authentication is needed. Please run:\naz login --scope http://169.254.169.254/.default\n" } } }

It occurs when request builder tries to get a token here, for host 169.254.169.254:

let bearer_token = this.client.bearer_token().await?;
req.insert_header(azure_core::headers::AUTHORIZATION, format!("Bearer {}", bearer_token.secret()));

But the thing is, IMDS doesn't require auth at all. I've removed code above so that request is sent without trying to get a token, and it works without problems.

cataggar commented 8 months ago

Yes, it probably does not need authentication. The spec defines it as:

  "securityDefinitions": {
    "azure_auth": {
      "type": "oauth2",
      "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize",
      "flow": "implicit",
      "description": "Azure Active Directory OAuth2 Flow",
      "scopes": {
        "user_impersonation": "impersonate your user account"
      }
    }
  },

Rather than the usual:

  "securityDefinitions": {
    "azure_auth": {
      "type": "oauth2",
      "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize",
      "flow": "implicit",
      "description": "Azure Active Directory OAuth2 Flow",
      "scopes": {
        "user_impersonation": "impersonate your user account"
      }
    }
  },

The services code gen doesn't currently look at the securityDefinitions. Instead of using azure_identity::DefaultAzureCredentialBuilder probably just implement a get_token that does not do anything. Try copying https://github.com/Azure/azure-sdk-for-rust/pull/1574/files to you project.