iControl REST Fine-Grained Role Based Access Control
Introduction
F5's role based access control (RBAC) mechanism allows a BIG-IP administrator to assign appropriate access privileges to the users (see Manual Chapter: User Roles). For example, with the
operator
role, the user is specifically allowed to enable or disable nodes and pool members. The mechanism is generally the best way to manage users easily and consistently, however, finer access management may be required from time to time: e.g., allow only to view the stats of a predefined set of virtuals. Restricting access is especially important in iControl REST because users can remotely and directly access the system.
The existing roles and their access permissions are defined in
/mgmt/shared/authz/roles
and /mgmt/shared/authz/resource-groups
. You can add custom roles with custom permissions for particular users to these resources (iControl REST endpoints). The resources are described in BIG-IQ Systems REST API References, however, they are not exactly easy to follow. To fill the gap, this article describes a method to configure users and roles in a much finer manner.
Note
This method is only applicable to iControl REST: It does not apply to Configuration Utility or ssh.
The method relies on the resources for local users (i.e.,
/mgmt/tm/auth/user
and /mgmt/shared/authz/users
). It does not work for remote authentication mechanisms such as RADIUS or Active Directory.
Setup
In this example, a local user "foo" and a custom role "testRole" are created. The role allows users to
GET
(list) only the virtual server "vs". The access method and resource are defined in "testResourceGroup", that is referenced from the "testRole". No other operation such as PATCH
(modify) or DELETE is permitted. Also, no other resource such as another virtual is allowed. All the REST calls are done using curl: You may want to consider using other methods such as F5 Python SDK .
1. Create a new user
The following curl command creates the user "foo". The password is "foo", the description is "Foo Bar", and the role is "operator" for all the partitions.
curl -sku admin:<pass> https://<mgmtIP>/mgmt/tm/auth/user -X POST -H "Content-Type: application/json" \ -d '{"name":"foo", "password":"foo", "description":"Foo Bar", "partitionAccess":[ { "name":"all-partitions", "role":"operator"} ] }'
You get the following JSON object:
{ "description": "Foo Bar", "encryptedPassword": "$6$jwL4UUxv$IUrzWGEUsyJaXlOB2oyyTPflHFdvDBXb6f3f/No4KNfQb.V6bpQZBgvxl3KkBDXGtpttej79DDphEGRh8d4iA/", "fullPath": "foo", "generation": 1023, "kind": "tm:auth:user:userstate", "name": "foo", "partitionAccess": [ { "name": "all-partitions", "nameReference": { "link": "https://localhost/mgmt/tm/auth/partition/all-partitions?ver=13.1.1.2" }, "role": "operator" } ], "selfLink": "https://localhost/mgmt/tm/auth/user/satoshi?ver=13.1.1.2" }
The role is important. When the access privileges conflict between the role and the fine grained RBAC, the stricter authorization is chosen. For example, if the RBAC is configured to allow PATCH or POST but the user's role is guest (no alteration allowed), the user won't be able to perform these methods.
You can create a user from tmsh or Configuration Utility if that's your preferred method.
2. (13.1.0 and later) Remove the user from /mgmt/shared/authz/roles/iControl_REST_API_User
/mgmt/shared/authz/roles/iControl_REST_API_User
From v13.1.0, a newly created local user is automatically added to
iControl_REST_API_User
, which grants access to iControl REST without any setup. To avoid assigning multiple permissions, you need to remove the user reference from /mgmt/shared/authz/roles/iControl_REST_API_User
.
First, get the data from
/mgmt/shared/authz/roles/iControl_REST_API_User
and redirect it to a file.
curl -sku admin:<pass> https://<mgmtIP>/mgmt/shared/authz/roles/iControl_REST_API_User \ | python -m json.tool > file
Edit the file. The file contains a line for the user "foo" like this.
"name": "iControl_REST_API_User", "userReferences": [ { "link": "https://localhost/mgmt/shared/authz/users/foo" }, ....
Remove the line including the opening and ending curly brackets plus the comma. Save the file.
Overwrite the current data by putting the file to the endpoint.
curl -sku admin:<pass> https://<mgmtIP>/mgmt/shared/authz/roles/iControl_REST_API_User -X PUT -d@file
3. Create a custom resource-group
A resource-group consists of a set of resources and methods. In this example, the resource-group is named "testResourceGroup", which allows a role to perform
GET
request to the resource /mgmt/tm/ltm/virtual/vs
. "testResourceGroup" is later used in the custom role.
curl -sku admin:<pass> https://<mgmtIP>/mgmt/shared/authz/resource-groups -X POST -H "Content-Type: application/json" \ -d '{"name":"testResourceGroup", "resources":[ {"restMethod":"GET", "resourceMask":"/mgmt/tm/ltm/virtual/vs" } ]}'
You get the following JSON object.
{ "id": "fe7a1ebc-3e61-30aa-8a5d-c7721f7c6ce2", "name": "testResourceGroup", "resources": [ { "resourceMask": "/mgmt/tm/ltm/virtual/vs", "restMethod": "GET" } ], "generation": 1, "lastUpdateMicros": 1521682571723849, "kind": "shared:authz:resource-groups:roleresourcegroupstate", "selfLink": "https://localhost/mgmt/shared/authz/resource-groups/fe7a1ebc-3e61-30aa-8a5d-c7721f7c6ce2" }
Note that a resource-group entry is keyed by "id", not "name". The id is automatically generated.
As you can see, the resources field is a list of multiple objects, each containing the endpoint and the method. To add more permissions to the resource-group, add objects to the list.
4. Create a custom role
Create a role "testRole" with the user "foo" and the resource-groups "testResourceGroup". This makes the user to become a member of the role "testRole", hence allows the users to perform
GET
only to the /mgmt/tm/ltm/virtual/vs
.
curl -sku admin:<pass> https://<mgmtIP>/mgmt/shared/authz/roles -X POST -H "Content-Type: application/json" \ -d '{"name":"testRole", "userReferences":[ {"link":"https://localhost/mgmt/shared/authz/users/foo"} ], "resourceGroupReferences":[{"link":"https://localhost/mgmt/shared/authz/resource-groups/fe7a1ebc-3e61-30aa-8a5d-c7721f7c6ce2"}]}'
Please note that the reference to the user foo in the userReferences field is different from Step #1: The user created was
/mgmt/tm/auth/user/foo
while the reference is /mgmt/shared/authz/users/foo
. The /mgmt/shared/authz/users/foo is automatically created. J
ust use /mgmt/shared/authz/users/
+ user name
.
Again, please observe that the resource-groups reference is not by name but by ID. See the selfLink in the step #3.
You get the following JSON object.
{ "name": "testRole", "userReferences": [ { "link": "https://localhost/mgmt/shared/authz/users/foo" } ], "resourceGroupReferences": [ { "link": "https://localhost/mgmt/shared/authz/resource-groups/fe7a1ebc-3e61-30aa-8a5d-c7721f7c6ce2" } ], "generation": 1, "lastUpdateMicros": 1521682931708662, "kind": "shared:authz:roles:rolesworkerstate", "selfLink": "https://localhost/mgmt/shared/authz/roles/testRole" }
Test
The following REST calls demonstrate that the user "foo" can
GET
the virtual "vs" but nothing else.
curl -D - -sku foo:foo https://192.168.226.155/mgmt/tm/ltm/virtual/vs | grep HTTP HTTP/1.1 200 OK curl -D - -sku foo:foo https://192.168.226.155/mgmt/tm/ltm/virtual | grep HTTP HTTP/1.1 401 F5 Authorization Required curl -D - -sku foo:foo https://192.168.226.155/mgmt/tm/ltm/virtual -X PATCH -d '{"test":"test"}' | grep HTTP HTTP/1.1 401 F5 Authorization Required curl -D - -sku foo:foo https://192.168.226.155/mgmt/tm/sys/version | grep HTTP HTTP/1.1 401 F5 Authorization Required
Cleanup
Removing users that are no longer used is a good admin practice. The cleanup procedure is described below (response JSON blobs are not shown):
1. Delete the resource-group. Use ID.
curl -sku admin:<pass> https://<mgmtIP>/mgmt/shared/authz/resource-groups/fe7a1ebc-3e61-30aa-8a5d-c7721f7c6ce2 -X DELETE
2. Delete the custom role.
curl -sku admin:<pass> https://<mgmtIP>/mgmt/shared/authz/roles/testRole -X DELETE
3. Delete the user.
You can perform this step from tmsh or Configuration Utility.
curl -sku admin:<pass> https://<mgmtIP>/mgmt/tm/auth/user/foo -X DELETE
- 235Nimbostratus
@Satoshi Toyosawa
Very cool article.
I don't understand and How user-foo is associated with the testRole?
Part 4,Below output have not the user foo.
"name": "testRole", "userReferences": [ { "link": "; } ], "resourceGroupReferences": [ { "link": "; } ], "generation": 1, "lastUpdateMicros": 1521682931708662, "kind": "shared:authz:roles:rolesworkerstate", "selfLink": "; }
Thanks
- Satoshi_Toyosa1Ret. Employee
Good spotting. Typo fixed. Thanks.
- JWhitesPro_1928Cirrostratus
What does the format look like if you have multiple resources in the resource mask or multiple methods?
To specify multiple resourses you will simply add them to the collection in the context of "resources" by using a PATCH method (a POST would overwrite the collection).
Below you will find some examples.virtuals GET ./mgmt/tm/ltm/virtual List all virtual servers (cannot list a specific one) GET ./mgmt/tm/ltm/virtual/* List specified virtual server (cannot list all) GET ./mgmt/tm/ltm/virtual/~~ List properties of specified virtual servers GET ./mgmt/tm/ltm/virtual/~~/* List properties (profiles, policies, ?) of specified virtual servers GET ./mgmt/tm/ltm/virtual/~~/profiles List profiles of specified virtual servers GET ./mgmt/tm/ltm/virtual/~~/policies List policies of specified virtual servers POST ./mgmt/tm/ltm/virtual/*/* Add properties (profiles, policies, ?) all virtual servers POST ./mgmt/tm/ltm/virtual/~~/* Add properties (profiles, policies, ?) of specified virtual servers POST ./mgmt/tm/ltm/virtual/~~/profiles Add profiles of specified virtual servers POST ./mgmt/tm/ltm/virtual/~~/policies Add policies of specified virtual servers PATCH ./mgmt/tm/ltm/virtual/* Modify properties all virtual servers PATCH ./mgmt/tm/ltm/virtual/~~ Modify properties of specified virtual servers DELETE ./mgmt/tm/ltm/virtual/*/*/* Delete properties (profiles, policies, ?) all virtual servers DELETE ./mgmt/tm/ltm/virtual/~~/*/* Delete properties (profiles, policies, ?) of specified virtual servers DELETE ./mgmt/tm/ltm/virtual/~~/profiles/* Delete profiles of specified virtual servers DELETE ./mgmt/tm/ltm/virtual/~~/policies/* Delete policies of specified virtual servers pools GET ./mgmt/tm/ltm/pool List all pools (cannot list a specific one) GET ./mgmt/tm/ltm/pool/* List specified pools (cannot list all) GET ./mgmt/tm/ltm/pool/~~ List properties of specified pools GET ./mgmt/tm/ltm/pool/~~/* List properties (members, ?) of specified pools GET ./mgmt/tm/ltm/pool/~~/members List Members of specified pools POST ./mgmt/tm/ltm/pool/*/* Add properties (members, ?) all pools POST ./mgmt/tm/ltm/pool/~~/* Add properties in specified pool POST ./mgmt/tm/ltm/pool/~~/members Add Members of specified pools DELETE ./mgmt/tm/ltm/pool/*/*/* Delete properties (members, ?) all pools DELETE ./mgmt/tm/ltm/pool/~~/*/* Delete properties in specified pool DELETE ./mgmt/tm/ltm/pool/~~/members/* Delete Members of specified pools PATCH ./mgmt/tm/ltm/pool/* Modify properties all pools PATCH ./mgmt/tm/ltm/pool/~~ Modify properties in specified pool PATCH ./mgmt/tm/ltm/pool/*/*/* Modify properties (members) all pools (administrative state) PATCH ./mgmt/tm/ltm/pool/~~/*/* Modify properties (members, ?) in specified pool (administrative state) PATCH ./mgmt/tm/ltm/pool/~~/members/* Modify Members of specified pools (administrative state) PATCH ./mgmt/tm/ltm/pool/~~/members/~~ Modify specified members of specified pools (administrative state)
- Peter_BaumannCirrostratus
Hello
Thanks, Peter
Hi Peter, no, it´s not. It seems to be reboot-proof. But it had to be restored after a software update. No idea, where the information is stored. We kept it in a script (stored in /config/) directory and executed it conditionally via /config/startup. Thanks, Stephan
- SteveGoldNimbostratus
Hi Stephen, We are using Big-IP 13.1.0.3 Build 0.0.5 Point Release 3.
It seems to work only when we leave the user "foo" in the iControl_REST_API_User reference group... When we delete its reference we get an 401 Authorization error... Do you know what might be the problem? Thank you, Steve
Hi Steve,
- SteveGoldNimbostratus
Hi Stephan, Thank you very much for the quick response!
The problem is that if we don`t delete the user from the iControl_REST_API_User reference group, it gets administrative permissions so that the RBAC model becomes irrelevant.
So the Rest API RBAC model does not work on Big-IP v13...?
Thank you, Steve
Hi Steve, I will check it tonight while travelling and provide an update. Will also check it´s behaviour on reboot and config restore. Cheers, Stephan