If you create a Service Principal for your VM, and push somehow the credentials on the VM, you can avoid MSI. But MSI was created on purpose to avoid that, since it's not really a simple process nor safe to push credentials inside a VM.
To assign a role to an Active Directory ID (whatever using MSI or dedicated ServicePrincipal), you can use this code to assign role (using azure-mgmt-authorization
package).
https://github.com/Azure-Samples/compute-python-msi-vm#role-assignement-to-the-msi-credentials
# Get "Contributor" built-in role as a RoleDefinition object
role_name = 'Contributor'
roles = list(authorization_client.role_definitions.list(
resource_group.id,
filter="roleName eq '{}'".format(role_name)
))
assert len(roles) == 1
contributor_role = roles[0]
# Add RG scope to the AD id
# This assumes "sp_id" is either a MSI id or a SP id
role_assignment = authorization_client.role_assignments.create(
resource_group.id,
uuid.uuid4(), # Role assignment random name
{
'role_definition_id': contributor_role.id,
'principal_id': sp_id
}
)
Then this AD id will be able to act only on that role and nothing more.