azure-sdk-for-java
azure-sdk-for-java copied to clipboard
[BUG] com.azure.resourcemanager.AzureResourceManager.Authenticated.activeDirectoryUsers() are returning null
Describe the bug All methods of the com.azure.resourcemanager.authorization.models.ActiveDirectoryUser obtained via com.azure.resourcemanager.AzureResourceManager.Authenticated.activeDirectoryUsers() are returning null (except for basic properties like principalName and id, for example).
Steps to reproduce the behavior: 1 - Configure credentials and create com.azure.resourcemanager.AzureResourceManager; 2 - List activeDirectoryUsers() and call methods;
Code Snippet
package br.com.luiscavalcantidev.azure.activedirectory;
import com.azure.core.management.AzureEnvironment;
import com.azure.core.management.profile.AzureProfile;
import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.azure.resourcemanager.AzureResourceManager;
import com.azure.resourcemanager.AzureResourceManager.Authenticated;
import com.azure.resourcemanager.authorization.fluent.models.MicrosoftGraphUserInner;
import com.azure.resourcemanager.authorization.models.ActiveDirectoryUser;
public class AzureActiveDirectoryApp {
public static void main(String[] args) {
final String subscriptionId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
final String applicationId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
final String tenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
final String secret = "xx.xxxxxxxxxxxx_xx_xxxxxxxxxxxxxxx";
final AzureProfile azureProfile = new AzureProfile(tenantId, subscriptionId, AzureEnvironment.AZURE);
final ClientSecretCredential secretCredential = new ClientSecretCredentialBuilder()
.clientId(applicationId)
.clientSecret(secret)
.tenantId(tenantId)
.build();
final Authenticated azureResourceManager = AzureResourceManager.configure()
.authenticate(secretCredential, azureProfile);
for (ActiveDirectoryUser user : azureResourceManager.activeDirectoryUsers()
.list()) {
final MicrosoftGraphUserInner innerModel = user.innerModel();
// Do not return null
System.out.println("user.id :" + user.id());
System.out.println("user.mail :" + user.mail());
System.out.println("user.principalName :" + user.userPrincipalName());
System.out.println("innerModel.displayName :" + innerModel.displayName());
// Return null
System.out.println("innerModel.userType :" + innerModel.userType());
System.out.println("innerModel.creationType :" + innerModel.creationType());
System.out.println("innerModel.accountEnabled :" + innerModel.accountEnabled());
System.out.println("innerModel.createdDateTime :" + innerModel.createdDateTime());
System.out.println("innerModel.lastPasswordChangeDateTime :" + innerModel.lastPasswordChangeDateTime());
}
}
}
Expected behavior Response with all methods returning what they "should" in the same way as console/CLI.
Screenshots
Setup: OS: Linux/Windows IDE: Apache NetBeans 15 Library/Libraries: com.azure.resourcemanager 2.12.0 Java version: 8
Additional context We have all necessary/additional application API permissions for this operation: User.Read.All, Group.Read.All, Directory.Read.All and GroupMember.Read.All.
@weidongxu-microsoft could you please take a look at this issue reported by @luisCavalcantiDev
@XiaofeiCao Could you take a look?
There could be some field that not populated during List, but have value when Get on single item.
@luisCavalcantiDev
PS: if you are doing advanced work on MSGraph, you might want to use their dedicated SDK here https://github.com/microsoftgraph/msgraph-sdk-java
@luisCavalcantiDev Seems that default list returns only these properties(id, name, etc).
You can add select
parameter to enable retrieval of the properties you need:
final String consistencyLevel = null;
final Integer top = null;
final Integer skip = null;
final String search = null;
final String filter = null;
final Boolean count = null;
final List<Get6ItemsItem> orderby = null;
// add properties you need to the list
final List<Get7ItemsItem> select = List.of(
Get7ItemsItem.ID,
Get7ItemsItem.MAIL,
Get7ItemsItem.USER_PRINCIPAL_NAME,
Get7ItemsItem.DISPLAY_NAME,
Get7ItemsItem.USER_TYPE,
Get7ItemsItem.CREATION_TYPE,
Get7ItemsItem.ACCOUNT_ENABLED,
Get7ItemsItem.CREATED_DATE_TIME,
Get7ItemsItem.LAST_PASSWORD_CHANGE_DATE_TIME
);
final List<Get8ItemsItem> expand = null;
for (MicrosoftGraphUserInner innerModel : azureResourceManager.activeDirectoryUsers()
.manager().serviceClient().getUsersUsers().listUser(consistencyLevel, top, skip, search, filter, count, orderby, select, expand, Context.NONE)) {
// Do not return null
System.out.println("user.id :" + innerModel.id());
System.out.println("user.mail :" + innerModel.mail());
System.out.println("user.principalName :" + innerModel.userPrincipalName());
System.out.println("innerModel.displayName :" + innerModel.displayName());
// Should return non-null value for existing properties
System.out.println("innerModel.userType :" + innerModel.userType());
System.out.println("innerModel.creationType :" + innerModel.creationType());
System.out.println("innerModel.accountEnabled :" + innerModel.accountEnabled());
System.out.println("innerModel.createdDateTime :" + innerModel.createdDateTime());
System.out.println("innerModel.lastPasswordChangeDateTime :" + innerModel.lastPasswordChangeDateTime());
}
@XiaofeiCao
If those fields are exposed by AADUser model, we probably should set them in select
on our list
API.
But if these fields are not exposed, user is recommended to use MSGraph lib. The few AAD related API in this lib is mostly for getting an AADUser and assign some access control to it via RBAC, not actually for managing AAD users.
@weidongxu-microsoft
The fields are exposed in MicrosoftGraphUserInner
.
In portal, list
and get
use different sets of select
paramters. The properties that this issue requests (createdDateTime, accountEnabled, etc) is not included in list
but rather in get
.
We can use same sets of select
to align with portal. But I'm not sure this is what the issue wants.
@XiaofeiCao I mean our handwritten model, not the Inner one (we assume user will not use the Inner, if they use, they are on their own).
@weidongxu-microsoft
Oh, sorry. They are not exposed in our handwritten model ActiveDirectoryUser
.
Hi @luisCavalcantiDev. Thank you for opening this issue and giving us the opportunity to assist. We believe that this has been addressed. If you feel that further discussion is needed, please add a comment with the text “/unresolve
” to remove the “issue-addressed” label and continue the conversation.
/unresolve
@XiaofeiCao, @weidongxu-microsoft thanks for the replies.
The suggestion of using selection as an argument to the User list is working.
However, I understand the original method I used is broken the way it is, since there is nothing suggesting the returned objects will be half populated. Either the current behavior should be documented or it should be fixed to populate all properties as expected.
@XiaofeiCao
If those fields are exposed by AADUser model, we probably should set them in
select
on ourlist
API.But if these fields are not exposed, user is recommended to use MSGraph lib. The few AAD related API in this lib is mostly for getting an AADUser and assign some access control to it via RBAC, not actually for managing AAD users.
@luisCavalcantiDev The simple thing is that we don't recommend to use this lib to manage AAD user. Please switch to https://github.com/microsoftgraph/msgraph-sdk-java
@weidongxu-microsoft We're taking a look at the API you recommended, despite our intention being simply to perform read only operations, not to manage users or groups. However, there is no clear statement in the documentation about the limitations of the API we're using and AADUser IinnerModel having many methods which seem to return relevant information but end up being useless may confuse users.
@luisCavalcantiDev
Some context, the innerModel
is considered an implementation detail, and serves as an escape-hatch -- when user cannot find the property from other getters, they can try query there, as service may add new JSON property without our notice.
However, the drawback is that it is not something guaranteed (we don't test these), and it might get broken without notice (as it is considered implementation detail). Actually, we had already changed that detail when upgrading from AD Graph to MS Graph around SDK version 2.2.0.
Similar about the REST API reported by Xiaofei https://github.com/Azure/azure-sdk-for-java/issues/30981#issuecomment-1249042764. It is regarded as implementation, as hinted by the meaningless naming.
Sorry about above not well documented.
I will leave the decision to @XiaofeiCao, of whether to add an overload of "list" with "select" parameter to let you input the required properties as String
.
But know that this would not be our priority. Our priority is still to better provide the feature to manage Azure resource (this does not include AAD), and AAD is only included to provide easy-to-use RBAC on the Azure resource.