Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot use a User Assigned Managed Identity with azure_identity 0.20.0 #1659

Open
johnbatty opened this issue May 14, 2024 · 5 comments · May be fixed by #1660
Open

Cannot use a User Assigned Managed Identity with azure_identity 0.20.0 #1659

johnbatty opened this issue May 14, 2024 · 5 comments · May be fixed by #1660

Comments

@johnbatty
Copy link
Contributor

Using azure_identity prior to 0.20.0 I was able to use specific User Assigned Managed Identity credentials like this:

ImdsManagedIdentityCredential::default()
                    .with_object_id(&managed_identity_object_id)

For 0.20.0 there was an overhaul of how credentials are created, and it no longer appears possible to create an ImdsManagedIdentity with an object_id.

This is a major issue for my project (and I imagine others) - we rely on User Assigned Managed Identities so can't upgrade azure_identity without a fix to restore this capability.

I do note there is an outstanding issue for creating a ManagedIdentityCredential: #1536

I'm happy to make a fix, but need to agree what the API should look like.

  • In 0.19.0 the implementation of ImdsManagedIdentityCredential had methods to allow you to set one of object_id, client_id or identity (resource id).
    • Ideally we should be able to use any of these methods
  • The current 0.20.0 ImdsManagedIdentityCredential implementation does have an enum defined that includes all the different types of ImdsManagedIdentityCredential, so we just need to provide a way to create instances with an id of each of these types.
    pub(crate) enum ImdsId {
        SystemAssigned,
        ClientId(String),
        ObjectId(String),
        MsiResId(String),
    }

The previous method of creating an ImdsManagedIdentityCredential and then calling one of the other methods to set a value felt a bit hacky. Might be simpler to expose the above ImdsId enum in the public API, and then allow it to be passed in a new constructor.
Although possibly a bit odd passing in ImdsId to a ManagedIdentityCredential (without the Imds prefix). Could rename ImdsId in the API, perhaps:

ManagedIdentityCredential::new(id: ImdsId, options: impl Into<TokenCredentialOptions>)

For comparison, the .NET SDK ManagedIdentityCredential has multiple overloaded constructors for creating the different variants:

Any thoughts/suggestions appreciated.

@cataggar
Copy link
Member

You are on the right track @johnbatty. Please see this discussion for context.

@cataggar
Copy link
Member

cataggar commented May 14, 2024

I made it public again in #1660, but it should probably be private long term. Are you looking for VirtualMachineManagedIdenityCredential, but with a way to specify the user assigned managed identity?

@johnbatty
Copy link
Contributor Author

@cataggar

I made it public again in #1660, but it should probably be private long term.

Thank you!

Are you looking for VirtualMachineManagedIdenityCredential, but with a way to specify the user assigned managed identity?

Yes

@johnbatty
Copy link
Contributor Author

@cataggar

Perhaps we could just update the VirtualMachineManagedIdentityCredential constructor to take an additional id parameter, which would then allow it to be used for either System Assigned or User Assigned ids?

Current:

    pub fn new(options: impl Into<TokenCredentialOptions>) -> Self {
        let endpoint = Url::parse(ENDPOINT).unwrap(); // valid url constant
        Self {
            credential: ImdsManagedIdentityCredential::new(
                options,
                endpoint,
                API_VERSION,
                SECRET_HEADER,
                SECRET_ENV,
                ImdsId::SystemAssigned,
            ),
        }
    }

New:

    pub fn new(id: ImdsId, options: impl Into<TokenCredentialOptions>) -> Self {
        let endpoint = Url::parse(ENDPOINT).unwrap(); // valid url constant
        Self {
            credential: ImdsManagedIdentityCredential::new(
                options,
                endpoint,
                API_VERSION,
                SECRET_HEADER,
                SECRET_ENV,
                id,
            ),
        }
    }

@cry-inc
Copy link

cry-inc commented Jun 5, 2024

I have a similar issue and also had to revert back to 0.19 because 0.20 did not allow me to create a managed identity credentials with a customized client ID.

My application runs normally in a Azure Batch VM with a identity specified from an ENV variable, but I also need to be able to run it locally with my Azure CLI credentials.

Right now I use code that looks like this:

let credentials: Arc<dyn TokenCredential> = if let Some(client_id) = &args.batch_task_identity {
    Arc::new(ImdsManagedIdentityCredential::default().with_client_id(client_id))
} else {
    Arc::new(DefaultAzureCredential::default())
};

Maybe it would be possible to specify custom IDs for managed identities by extending the TokenCredentialOptions struct introduced in 0.20?

If this struct would include options for the customized client IDs for the managed identity credentials, the code could be simplified to something like that:

let mut options = TokenCredentialOptions::default();
options.set_managed_identity_client_id(args.batch_task_identity);
let credentials = Arc::new(DefaultAzureCredential::create(options)?);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants