f5-common-python
f5-common-python copied to clipboard
Add rest-proxy URI support
This is related to: https://github.com/F5Networks/f5-icontrol-rest-python/issues/111
iWorkflow / BIG-IQ (?) support REST proxy URI. This makes it possible to apply tenant RBAC on the REST endpoints (i.e. limit a user to only be able to modify a single BIG-IP LTM pool in a single Partition).
Documented here: https://devcentral.f5.com/wiki/iControl.REST_proxy_APIs.ashx
Example of one of the changes required (this is not meant to be a "good" example, but it gets the job done). This was done to monkey patch the library:
class ManagementRootProxy(ManagementRoot):
"""An interface to a multiple BIG-IP"""
def __init__(self, hostname, username, password, device_uuid, **kwargs):
timeout = kwargs.pop('timeout', 30)
port = kwargs.pop('port', 443)
icontrol_version = kwargs.pop('icontrol_version', '')
if kwargs:
raise TypeError('Unexpected **kwargs: %r' % kwargs)
# _meta_data variable values
iCRS = iControlRESTSession(username, password, timeout=timeout)
# define _meta_data
self._meta_data = {
'allowed_lazy_attributes': [Tm, Cm, Shared],
'hostname': hostname,
'port': port,
'uri': 'https://%s:%s/mgmt/shared/resolver/device-groups/cm-cloud-managed-devices/devices/%s/rest-proxy/mgmt/' % (hostname, port,device_uuid),
'icr_session': iCRS,
'device_name': None,
'local_ip': None,
'bigip': self,
'icontrol_version': icontrol_version,
'username': username,
'password': password,
'tmos_version': None,
}
self._get_tmos_version()
@chen23 is this still a desirable feature for your use-case?
@caphrim007 @pjbreaux my understanding is that @chen23 is using the SDK to integrate F5 devices with Kubernetes.
I'm very interested in supporting this use-case.
Is it the case that adding URI-proxy support will facilitate Kubernetes integrations?
Is there potential for implementing Kubernetes integrations in Ansible playbooks?
@zancas we could do ansible playbooks for kubernetes. I dont know the details about what @chen23 had in mind. I have iWorkflow vagrant boxes we can use for functional tests of this proxy feature
@zancas @caphrim007 @pjbreaux The URI-proxy support is intended to provide support for use-cases where a customer may want to limit access to the REST API to only allow limited actions (i.e. up/down pool members). https://devcentral.f5.com/questions/iworkflow-20-allowed-rest-uri-mask-in-user-roles-48058 This is useful in a multi-tenant environment and/or shared services.
@zancas so then, "yes", @chen23 still wants this.
@chen23 this functionality now exists in the iworkflow portion of the SDK. Do you want it for BIG-IQ as well?
@caphrim007 iWf is good for now. Thank you for adding!
I only have BIG-IQ and currently use the rest-proxy with some homebrew scripts. If it's not too much effort, I'd appreciate it if the BIG-IQ API could have this feature too.
@vsnine I will take a look.
@vsnine do you use it for managed, or unmanaged devices? or both? fwiw I have no idea if it supports both.
@chen23 here are the docs about it
http://f5-sdk.readthedocs.io/en/latest/userguide/rest_proxies.html
@caphrim007 currently all of our devices are fully managed.
I'd appreciate it if the proxy class for BigIQ was added to the API
edit: Github says I just unassigned some people from the issue. I have no idea how that happened. I shouldn't have permissions on this repo
I looked into this more as I am beginning more serious work with the SDK, and ran into a few issues with the iWorkflow REST proxy as it is when used with BIG-IQ CM.
In _get_device_uuid
the code assumes that the devices are located in the device group cm_cloud_managed_devices
which I don't believe exists in BIG-IQ by default. The SDK is hard-coded so adding other groups is a problem.
https://github.com/F5Networks/f5-common-python/blob/af2746d73d7f888cf64fe7db8dfe254867ceafd7/f5/iworkflow/init.py#L178
A workaround in BIG-IQ is to create the group cm-cloud-managed-devices
by sending a POST with the needed json payload. (Creating it via the webui results in the name of the group using underscores instead of dashes. )
{ "autoManageLocalhost": true,
"displayName": "cm-cloud-managed-devices",
"groupName": "cm-cloud-managed-devices",
"infrastructure": false,
"isViewGroup": false,
"kind": "shared:resolver:device-groups:devicegroupstate",
"properties": { "cm:gui:module": [ "adc",
"device",
"networksecurity",
"asmsecurity"]},
"selfLink": "https://localhost/mgmt/shared/resolver/device-groups/cm-cloud-managed-devices"}
I found an additional issue when attempting to create the group as a dynamic type and telling it to include all devices in BIG-IQ. If the group is a dynamic type, it seems to be returned as a different type of object, and _get_device_uuid
fails with AttributeError: '<class 'f5.iworkflow.shared.resolver.device_groups.cm_cloud_managed_devices.Device'>' object has no attribute 'pop'
I added a try/except block which catches the issue:
https://github.com/F5Networks/f5-common-python/blob/af2746d73d7f888cf64fe7db8dfe254867ceafd7/f5/iworkflow/init.py#L196
try:
return resource.pop('uuid', None)
except AttributeError: # needed if group is a dynamic group
return resource.uuid
@vsnine I'm new to using this package, but my assumption from up above was that a different proxy class using a slightly different API would have to be written for BigIQ. However, I'm 99% certain that the hard coded reference to cm_cloud_managed_devices
is a bug given that device group is an argument to that class.
In any case, I find it odd that the Proxy is composed the way it is. It'd make more sense to me that a iWorkflow or BigIQ MangementRoot instance would be passed in as a proxy argument to a BigIP ManagementRoot (or maybe a specific BigIP ManagementRootProxy class) as an argument so that multiple BigIP instances could be constructed from the "master" instance.
But, like I said, I'm new to using this package.
@nugend I'd say you are right that a BIG-IQ flavoured proxy is needed. It probably is possible to pull the ManagementProxy functions out and place them in a spot where they can be used for both BIG-IQ and iWorkflow.