Add RBAC logic to salt module for ACL per UUID/name
Change-Id: I8158c53b51f2989bdc933b802890ab48498e3854
diff --git a/_modules/contrail.py b/_modules/contrail.py
index 89a4bb2..777c686 100644
--- a/_modules/contrail.py
+++ b/_modules/contrail.py
@@ -13,6 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from vnc_api.vnc_api import *
+from vnc_api.gen.resource_xsd import *
+from cfgm_common.exceptions import *
+from cfgm_common.rbaclib import *
+import cfgm_common
+
from netaddr import IPNetwork
from vnc_api.vnc_api import PhysicalRouter, PhysicalInterface, LogicalInterface
from vnc_api.vnc_api import EncapsulationPrioritiesType
@@ -2103,3 +2109,289 @@
vnc_client.floating_ip_pool_update(fip_obj)
return ret
+
+
+def show_rbac_rules(api_access_list_entries):
+ if api_access_list_entries is None:
+ return 'Empty RBAC group!'
+
+ rule_list = api_access_list_entries.get_rbac_rule()
+ response = 'Rules (%d):' % len(rule_list) + '----------\n'
+ for idx, rule in enumerate(rule_list):
+ o = rule.rule_object
+ f = rule.rule_field
+ ps = ', '.join([p.role_name+':'+p.role_crud for p in rule.rule_perms])
+ o_f = "%s.%s" % (o, f) if f else o
+ response += '%2d %-32s %s\n' % (idx, o_f, ps)
+ return response
+
+
+def vnc_read_obj(vnc, obj_type, fq_name):
+ method_name = obj_type.replace('-', '_')
+ method = getattr(vnc, "%s_read" % (method_name))
+ try:
+ return method(fq_name=fq_name)
+ except NoIdError:
+ print '%s %s not found!' % (obj_type, fq_name)
+ return None
+
+
+def rbac_show_group(name, uuid, **kwargs):
+ '''
+ Show specific RBAC group
+
+
+ CLI Example
+ .. code-block:: bash
+ salt-call contrail.rbac_show_group name \
+ 'default-domain:default-project:default'
+
+ params:
+ name - one of pair {name, uuid} addresing to access-list
+ uuid(str) - UUID in case of "uuid" specified OR full RBAC group name \
+ including domain and project
+
+ '''
+ vnc = _auth(**kwargs)
+ fq_name = vnc.id_to_fq_name(uuid) if name == 'uuid' else uuid.split(':')
+ ret = {'name': fq_name,
+ 'changes': {},
+ 'result': True,
+ 'comment': ''}
+ rg = vnc_read_obj(vnc, 'api-access-list', fq_name)
+ if not rg:
+ ret['comment'] = 'No rules found'
+ return ret
+
+ ret['comment'] = show_rbac_rules(rg.get_api_access_list_entries())
+ return ret
+
+
+def rbac_create_group(uuid, **kwargs):
+ '''
+ Create RBAC group
+
+ CLI Example
+ .. code-block:: bash
+ salt-call contrail.rbac_create_group name \
+ 'default-domain:default-project:default'
+
+ params:
+ name - one of pair {name, uuid} addresing to access-list
+ uuid(str) - UUID in case of "uuid" specified OR full RBAC group name \
+ including domain and project
+
+ '''
+ vnc = _auth(**kwargs)
+ fq_name = uuid.split(':')
+ ret = {'name': fq_name,
+ 'changes': {},
+ 'result': True,
+ 'comment': ''}
+ if len(fq_name) != 2 and len(fq_name) != 3:
+ ret['comment'] = 'Fully qualified name of rbac group expected'
+ return ret
+
+ name = fq_name[-1]
+
+ if len(fq_name) == 2:
+ if fq_name[0] == 'default-global-system-config':
+ pobj = vnc.global_system_config_read(fq_name=fq_name[0:1])
+ else:
+ pobj = vnc.domain_read(fq_name=fq_name[0:1])
+ else:
+ pobj = vnc.project_read(fq_name=fq_name[0:2])
+
+ rentry = RbacRuleEntriesType([])
+ rg = ApiAccessList(name, parent_obj=pobj, api_access_list_entries=rentry)
+
+ if __opts__['test']:
+ ret['result'] = None
+ ret['comment'] = "RBAC group " + uuid + " will be created"
+
+ return ret
+ else:
+ vnc.api_access_list_create(rg)
+ rg2 = vnc.api_access_list_read(fq_name=fq_name)
+ rge = rg.get_api_access_list_entries()
+ show_rbac_rules(rge)
+ ret['comment'] = "RBAC group " + uuid + " has been created"
+
+ return ret
+
+
+def rbac_delete_group(name, uuid, **kwargs):
+ '''
+ Delete RBAC group
+
+ CLI Example
+ .. code-block:: bash
+ salt-call contrail.rbac_delete_group name \
+ 'default-domain:default-project:default'
+
+ params:
+ name - one of pair {name, uuid} addresing to access-list
+ uuid(str) - UUID in case of "uuid" specified OR full RBAC group name \
+ including domain and project
+
+ '''
+ vnc = _auth(**kwargs)
+ fq_name = vnc.id_to_fq_name(uuid) if name == 'uuid' else uuid.split(':')
+ ret = {'name': fq_name,
+ 'changes': {},
+ 'result': True,
+ 'comment': ''}
+ if len(fq_name) != 2 and len(fq_name) != 3:
+ ret['comment'] = 'Fully qualified name of rbac group expected'
+ return ret
+ name = fq_name[-1]
+
+ rg = vnc_read_obj(vnc, 'api-access-list', fq_name)
+ if not rg:
+ ret['comment'] = 'No rules found'
+ return ret
+ rge = rg.get_api_access_list_entries()
+ show_rbac_rules(rge)
+
+ if __opts__['test']:
+ ret['result'] = None
+ ret['comment'] = "RBAC group " + uuid + " will be deleted"
+
+ return ret
+ else:
+ vnc.api_access_list_delete(fq_name=fq_name)
+ ret['comment'] = "RBAC group " + uuid + " has been deleted"
+
+ return ret
+
+
+def rbac_add_rule(name, uuid, add_rule, **kwargs):
+ '''
+ Add rule to specific RBAC group
+
+ CLI Example
+ .. code-block:: bash
+ salt-call contrail.rbac_add_rule name \
+ 'default-domain:default-project:default' \
+ '* admin:CRUD'
+
+ params:
+ name - one of pair {name, uuid} addresing to access-list
+ uuid(str) - UUID in case of "uuid" specified OR full RBAC group name \
+ including domain and project
+ rule(str) - Appropriate RBAC-based rule in format '<object, field> \
+ list of <role:CRUD>' to be added
+
+ '''
+ vnc = _auth(**kwargs)
+ fq_name = vnc.id_to_fq_name(uuid) if name == 'uuid' else uuid.split(':')
+ rule = build_rule(add_rule)
+ ret = {'name': fq_name,
+ 'changes': {},
+ 'result': True,
+ 'comment': ''}
+ if rule is None:
+ ret['comment'] = 'A rule string must be specified for this operation'
+ return ret
+
+ # rbac rule entry consists of one or more rules
+ rg = vnc_read_obj(vnc, 'api-access-list', fq_name)
+ if not rg:
+ ret['comment'] = 'No rules found'
+ return ret
+
+ rge = rg.get_api_access_list_entries()
+ if rge is None:
+ rge = RbacRuleEntriesType([])
+ show_rbac_rules(rge)
+
+ # avoid duplicates
+ match = find_rule(rge, rule)
+ if not match:
+ rge.add_rbac_rule(rule)
+ else:
+ build_perms(rge.rbac_rule[match[0]-1], match[3])
+
+ show_rbac_rules(rge)
+
+ if __opts__['test']:
+ ret['result'] = None
+ ret['comment'] = "Rule " + add_rule
+ ret['comment'] += " will be created for RBAC group " + uuid
+
+ return ret
+ else:
+ rg.set_api_access_list_entries(rge)
+ vnc.api_access_list_update(rg)
+ ret['comment'] = "Rule " + add_rule
+ ret['comment'] += " has been added for RBAC group " + uuid
+
+ return ret
+
+
+def rbac_delete_rule(name, uuid, del_rule, **kwargs):
+ '''
+ Delete rule to specific RBAC group
+
+ CLI Example
+ .. code-block:: bash
+ salt-call contrail.rbac_delete_rule name \
+ 'default-domain:default-project:default' \
+ '* admin:CRUD'
+
+ params:
+ name - one of pair {name, uuid} addresing to access-list
+ uuid(str) - UUID in case of "uuid" specified OR full RBAC group name \
+ including domain and project
+ rule(str) - Appropriate RBAC-based rule in format '<object, field> \
+ list of <role:CRUD>' to be deleted
+
+ '''
+ vnc = _auth(**kwargs)
+ fq_name = vnc.id_to_fq_name(uuid) if name == 'uuid' else uuid.split(':')
+ rg = vnc_read_obj(vnc, 'api-access-list', fq_name)
+ ret = {'name': fq_name,
+ 'changes': {},
+ 'result': True,
+ 'comment': ''}
+ if not rg:
+ ret['comment'] = 'No rules found'
+ return ret
+ rge = rg.get_api_access_list_entries()
+ show_rbac_rules(rge)
+
+ del_idx = re.match("^[0-9]+$", del_rule)
+ if del_idx:
+ del_idx = int(del_idx.group())
+ rc = len(rge.rbac_rule)
+ if del_idx > rc or del_idx < 1:
+ ret['comment'] = 'Invalid rule index to delete.'
+ ret['comment'] += 'Value must be 1-%d' % rc
+ return ret
+ match = (del_idx, True)
+ else:
+ rule = build_rule(del_rule)
+ match = find_rule(rge, rule)
+
+ if not match:
+ ret['comment'] = "Rule not found. Unchanged"
+ return ret
+ elif match[1]:
+ rge.rbac_rule.pop(match[0]-1)
+ else:
+ build_perms(rge.rbac_rule[match[0]-1], match[2])
+ show_rbac_rules(rge)
+
+ if __opts__['test']:
+ ret['result'] = None
+ ret['comment'] = "Rule " + del_rule
+ ret['comment'] += " will be cleared from RBAC group " + uuid
+
+ return ret
+ else:
+ rg.set_api_access_list_entries(rge)
+ vnc.api_access_list_update(rg)
+ ret['comment'] = "Rule " + del_rule
+ ret['comment'] += " has been cleared from RBAC group " + uuid
+
+ return ret