JAMSHAID
JAMSHAID

Reputation: 1357

user.permissionsBoundary returns NULL while retrieving information from AWS using Java SDK

I am using AWS Java SDK v2 to list users using the code defined here on the AWS GitHub repo.

 public static void listAllUsers(IamClient iam) {

    try {
        boolean done = false;
        String newMarker = null;

        while (!done) {
            ListUsersResponse response;

            ListUsersRequest request;
            if (newMarker == null) {
                request = ListUsersRequest.builder().build();
            } else {
                request = ListUsersRequest.builder()
                        .marker(newMarker).build();
            }

            response = iam.listUsers(request);

            for (User user : response.users()) {
                System.out.format("\n Retrieved user %s", user.userName());
                System.out.println("\nPermission Boundary: " + user.permissionsBoundary());
            }

            if (!response.isTruncated()) {
                done = true;
            } else {
                newMarker = response.marker();
            }
        }
    } catch (IamException e) {
        System.err.println(e);
        System.exit(1);
    }
}

It returns NULL for user.permissionsBoundary(). Here is the output for print statements in the above code.

 Retrieved user jamshaid
Permission Boundary: null

 Retrieved user luminadmin
Permission Boundary: null

 Retrieved user test
Permission Boundary: null

When I run the following command in AWS CloudShell on AWS console, it returns the PermissionBoundary for the users it is defined.

aws iam get-user --user-name test     

Here is the sample output from AWS CloudShell.
console output
I am using the same account to make both requests.

Upvotes: 1

Views: 216

Answers (2)

jccampanero
jccampanero

Reputation: 53441

I do not think it is an issue, but the programmed behavior. From the API docs:

IAM resource-listing operations return a subset of the available attributes for the resource. For example, this operation does not return tags, even though they are an attribute of the returned object. To view all of the information for a user, see GetUser.

This is stated as well in the API javadocs.

In the console you are using get-user, not list-users, and this is why the command is returning all the information about the user, PermissionsBoundary within it.

Please, try instead using:

aws iam list-users

and check the output, it should match the result you obtained with the Java SDK, it will not contain PermissionsBoundary either.

If you want to obtain the same results that you are currently getting with the command aws iam get-user --user-name test from Java code, you can use the getUser method in IamClient. Try Something like:

GetUserRequest request = GetUserRequest.builder()
  .userName("test")
  .build()
;

GetUserResponse response = iam.getUser(request);
User user = response.user();
System.out.println("\nPermission Boundary: " + user.permissionsBoundary());

The User class is reused in both operations, get and list, but only in the former all the fields are populated.

Upvotes: 1

smac2020
smac2020

Reputation: 10734

I have confirmed this behavior by setting a permission boundary on an IAM user in the AWS Management Console. I changed the ListUsers example to include this code:

 for(User user : response.users()) {
    System.out.format("\n Retrieved user %s", user.userName());
    AttachedPermissionsBoundary permissionsBoundary = user.permissionsBoundary();
    if (permissionsBoundary != null)
        System.out.format("\n Permissions boundary details %s", permissionsBoundary.permissionsBoundaryTypeAsString());
   }

...

The permissionsBoundary() method does return null - even though the permission is set. This is a bug.

My advice here is to log a Github issue here:

https://github.com/aws/aws-sdk-java-v2

I also tested this with Kotlin SDK. Same result.

suspend fun listAllUsers() {

        IamClient { region = "AWS_GLOBAL" }.use { iamClient ->
            val response = iamClient.listUsers(ListUsersRequest { })
            response.users?.forEach { user ->
                println("Retrieved user ${user.userName}")
                val permissionsBoundary = user.permissionsBoundary
                if (permissionsBoundary != null)
                    println("Permissions boundary details ${permissionsBoundary.permissionsBoundaryType.toString()}")

            }
        }
 }

Upvotes: 2

Related Questions