Using RBAC With iControlREST on BIG-IP

BIG-IP is able to use built-in Role-Based Access Control (RBAC) functionality.  The operator function will be used in this example.  This article gives some guidance on how you can use such a role in combination with a role of operator.

I am using Postman RESTclient for communicating with the BIG-IP (v12.1).

Note: Everywhere you see {{big_ip_a_mgmt}} this should be your BIG-IP_management_IP.  Or in Postman you could create an environmental value and stop retyping IP addresses. For those using Postman, the collection of used URIs has been added to this article and can be downloaded for your own use, here: https://github.com/gwolfis/iControl

If you want to have logging running (recommended), you should start a SSH session and use the following commands.  Use standard Unix commands to work with these files, such as tail, grep, and less.

  •  /var/log/restjavad-audit.0.log - shows all authentications to the iControl REST service. This is an ordered list of every REST call.
  • /var/log/restjavad.0.log - contains information about connections to the iControl REST service, such as errors returned.
  •  /var/log/icrd - shows the actions of the icrd process, which manages the threads for processing the REST calls.
  • /var/log/ltm - contains messages from mcpd, a process called by icrd that manages the system configuration.

 

Use basic authentication with admin rights to accomplish the following through Postman:

 GET https://{{big_ip_a_mgmt}}/mgmt/tm/auth/user #Use admin to view all users on the BIG-IP

 

For the next task you might want to copy some of the response body to tweak your own non-admin user.

 POST https://{{big_ip_a_mgmt}}/mgmt/tm/auth/user #Create a user and define partition access and role

 

{ "name": "testuser", 
  "password": "test", 
  "partitionAccess": 
     [ { "name": "all-partitions", "role": "operator" } 
     ] 
}

 

If you can't wait (like me), log into the BIG-IP with the just created user and test. Did it work?

 GET https://{{big_ip_a_mgmt}}/mgmt/shared/authz/users # To get the properties of the just created user account.

 

You need the selflink properties of 'testuser' to be copied and placed in the iControl_REST_API_User group.  The part to copy should look something like this:

"selfLink": "https://localhost/mgmt/shared/authz/users/testuser" 


# Show all available roles and search for iControl_REST_API_User
GET https://{{big_ip_a_mgmt}}/mgmt/shared/authz/roles 

 

Next step is to PATCH this user to the role group of iControl_REST_API_User.

# Add testuser to the iControl_REST_API_User group by copy and pasting underneath section in the body of the PATCH request.

PATCH https://{{big_ip_a_mgmt}}/mgmt/shared/authz/roles/iControl_REST_API_User


{ 
 "userReferences": 
  [ 
    { "link": "https://localhost/mgmt/shared/authz/users/testuser" }
  ] 
}

 

The response should include:

{ 
 "name": "iControl_REST_API_User", 
 "userReferences": 
  [ 
    { "link": "https://localhost/mgmt/shared/authz/users/testuser" }, 
   
     ----output omitted---

 

Test if the user is allowed to use iControlREST, change the basic auth settings into your created test account.

 GET https://{{big_ip_a_mgmt}}/mgmt/tm/ltm

 

Did it work? You should see something like this:

{ 
 "kind": "tm:ltm:ltmcollectionstate", 
 "selfLink": "https://localhost/mgmt/tm/ltm?ver=12.1.0", 
 "items": 
   [ 
     { "reference": { "link": "https://localhost/mgmt/tm/ltm/auth?ver=12.1.0" } }, 
     { "reference": { "link": "https://localhost/mgmt/tm/ltm/classification?ver=12.1.0" } },

          ----output omitted---

 

 

Since we are in operator mode we try to view a couple of things and modify poolmember states.

 
GET https://{{big_ip_a_mgmt}}/mgmt/tm/ltm/virtual   # Shows all configured virtual servers 
GET https://{{big_ip_a_mgmt}}/mgmt/tm/ltm/pool      # Shows all configured pools 
GET https://{{big_ip_a_mgmt}}/mgmt/tm/ltm/node      # Shows all nodes

 

As an operator you are allowed to change the node state.

 GET https://{{big_ip_a_mgmt}}/mgmt/tm/ltm/pool/pool_http/members # Show all poolmembers of pool pool_http

 

Select a poolmember of choice to change state

 GET https://{{big_ip_a_mgmt}}/mgmt/tm/ltm/pool/pool_http/members/~Common~10.128.20.11:80

 

A poolmember has three states:

- Enabled

- Disabled (existing sessions will continue, but no new sessions will be accepted)

- Force Offline (existing sessions will be dropped immediately, no new sessions accepted)

Note: There is a fourth state, but this one appears when the node is unavailable and is not relevant in this use case.  Also, with a node you will see the same states, but you want to manage the state at the pool member level instead of node level.  (read about pool members and nodes in F5 documentation if you don’t know.)

The states of the node are controlled by two parameters called "session" and "state"

Session: provides the function if existing sessions are allowed to continue, although the state is down (disabled mode), or should be dropped straight away (force offline)

State: facilitates if the node is up or down

 

Enabled in TMSH:          

 modify ltm node 10.128.20.11 session user-enabled state user-up   #(GUI: mark = green round)

Disabled in TMSH:         

 modify ltm node 10.128.20.11 session user-disabled state user-up  #(GUI: mark = black round)

Force offline in TMSH:   

 modify ltm node 10.128.20.11 session user-disabled state user-down  #(GUI: mark = black diamond)

 

So how does this work with iControlREST:

 PATCH https://{{big_ip_a_mgmt}}/mgmt/tm/ltm/pool/pool_http/members/~Common~10.128.20.11:80

 

 { "session":"user-enabled", "state": "user-down" }

Since you know the different values to change session and state, use them to play around and check the status of the respected node once you have done a modification.

You could go through the same for other roles and start exploring how to use them with iControl; the setup is the same.

So what if you want to clean up a bit since the user is no longer needed?  (don’t forget to change your basic authentication to "admin" first before trying to delete the user)

 DELETE https://{{big_ip_a_mgmt}}/mgmt/shared/authz/users/testuser

 

Confirm by doing the following checks:

GET https://{{big_ip_a_mgmt}}/mgmt/shared/authz/roles/iControl_REST_API_User   #Check if the non-admin user is removed. 
GET https://{{big_ip_a_mgmt}}/mgmt/tm/auth/user #Check if the non-admin user is removed.

 

I hope that this helps in gaining understanding how a BIG-IP is able to add a non-admin user to the iControl_REST_API_User role. 

Additional documentation can be found in the User Guide for iControl REST interface in BIG-IP version 11.6
The document explains how you can add users to the role of iControl_REST_API_User.

Published Dec 22, 2016
Version 1.0

Was this article helpful?

3 Comments

  • A common mistake is trying to use the PUT method to do this Operator-level event, and it simply will not work. The reason is that the PUT method saves ALL attributes of the object, which is not permitted under the Operator role.

     

    This is true of all roles. If you are not an Admin role, then Patch is your preferred, and pretty much required, method.

     

  • I've playing around with the iControl feature. My goal is to setup a monitoring solution based on iControl possibilities.

     

    Now I've the following issue:

     

    Using the local admin accont will work. I can read and write data:

     

    curl -sk -u admin https://HOSTNAME/mgmt/tm/ltm/pool/POOLNAME/members/~Common~NODENAME -H "Content-Type: application/json" -X PATCH -d '{ "session":"user-enabled", "state":"user-down" }'
    

    Using an ActiveDirectory Account I can read data, but if I try to write data using the command from above I'll get the following issue:

     

    {"code":400,"message":"Found unexpected URI tmapi_mapper/ltm/~Common~pool/POOLNAME/members/~Common~NODENAME.","errorStack":[],"apiError":1}
    

    Now I don't know whats the problem here. I already tested a lot with different passwords, user roles, the Header X-F5-Auth-Token, patching the iControl_REST_API_User Group... nothing will work. Does anyone else has an idea what I can test now?

     

    Thanks...