Role-Based Access Control (RBAC) configuration examples
This topic provides examples of RBAC configurations set in different scenarios using properties and user tagging scripts.
Example 1
You want to provide or maintain a map of functional Ids and associated user groups, so the user with groups associated with some functional IDs can access app data with a username equal to the functional ID.
Group G1 is mapped to functional IDs U1 and U2, so users belonging to G1 can access the data with usernames U1 or U2.
Create one role for each function ID, assign the groups applicable and apply the filter.
com.unraveldata.rbac.roles role1,role2,...
com.unraveldata.rbac.role.role1.groups G1,..
com.unraveldata.rbac.role.role1.views clusters.resources,clusters.chargeback,clusters.workload,jobs
com.unraveldata.rbac.role.role1.data.field.userName <functionId>
,$user
Create a role with fids tag using properties:
com.unraveldata.rbac.roles=fid com.unraveldata.rbac.role.fid.groups=group1,group2,group3,.. com.unraveldata.rbac.role.fid.data.field.userName=$tags.fids
User tagging script
Input file:
functional_ids_groups.csv
Input file content:
Functional Ids;Groups ala;ux-rg-bd-scealadlbiro-dev bda;ux-rg-bd-bigdataadmins user6;dummy-groups06,dummy-group12 user7;dummy-group12
Script file content:
const path = require('path'); const fs = require('fs'); const inputFileName = 'functional_ids_groups.csv'; const inputFilePath = path.join(__dirname, inputFileName); function union(arr1, arr2) { const arr = []; const obj = {}; for (let i = 0; i < arr1.length; i += 1) { arr.push(arr1[i]); obj[arr1[i]] = true; } for (let i = 0; i < arr2.length; i += 1) { if (!obj[arr2[i]]) { arr.push(arr2[i]); } } return arr; } function getGroupsFunctionalIdsMap() { let fd; const groupsFIdsMap = {}; try { fd = fs.openSync(inputFilePath, 'r'); } catch (err) { console.error('RBAC : could not open functional_ids_groups.csv file; file path =', inputFilePath); console.error(err); return {}; } try { const txt = fs.readFileSync(fd, 'utf-8'); if (typeof txt === 'string' && txt.length > 0) { const lines = txt.trim().split(/\r?\n/); for (let i = 1; i < lines.length; i += 1) { const line = lines[i]; const fIdsGroups = line.split(';'); const fIds = fIdsGroups[0].split(','); const groups = fIdsGroups[1].split(','); const formattedFIds = []; const formattedGroups = []; for (let j = 0; j < fIds.length; j += 1) { const formattedFId = fIds[j].trim(); if (formattedFId) { formattedFIds.push(formattedFId); } } for (let j = 0; j < groups.length; j += 1) { const formattedGroup = groups[j].trim().toLowerCase(); if (formattedGroup) { formattedGroups.push(formattedGroup); } } for (let j = 0; j < formattedGroups.length; j += 1) { const formattedGroup = formattedGroups[j]; if (groupsFIdsMap[formattedGroup]) { groupsFIdsMap[formattedGroup] = union(groupsFIdsMap[formattedGroup], formattedFIds); } else { groupsFIdsMap[formattedGroup] = formattedFIds; } } } } return groupsFIdsMap; } catch (err) { console.error('RBAC : could not create Groups Functional IDS Map.'); console.error(err); return {}; } finally { fs.closeSync(fd); } } const groupsFIdsMap = getGroupsFunctionalIdsMap(); console.log('RBAC : Groups & Functional IDS Map -', JSON.stringify(groupsFIdsMap)); function getTags(username, userGroups) { const tags = {}; if ( Object.keys(groupsFIdsMap).length === 0 || !Array.isArray(userGroups) || userGroups.length === 0 ) { return tags; } let fIds = []; for (let i = 0; i < userGroups.length; i += 1) { const userGroup = userGroups[i].toLowerCase(); const fId = groupsFIdsMap[userGroup]; if (fId && fId.length > 0) { fIds = union(fIds, fId); } } if (fIds.length > 0) { tags.fids = fIds; } return tags; } module.exports = getTags;
Example 2
You want the users to access only a specific Workspace or Cluster.
user1 belonging to group GRP_A can only view data for all clusters in workspace DBWkps1.
user2 belonging to groups GRP_B can only view the data in clusters Cluster1 and Cluster2.
user3 belonging to group GRP_C can only view data in all clusters in workspace DBWkps2 and only Cluster3, Cluster4 in another workspace.
##roles list com.unraveldata.rbac.roles=role1, cluster_1_2, workspace1, workspace_cluster ##workspace1 role config com.unraveldata.rbac.role.workspace1.users= user1 ##Optional com.unraveldata.rbac.role.workspace1.groups=GRP_A com.unraveldata.rbac.role.workspace1.views=clusters.resources, clusters.chargeback, compute, jobs ##Set which tabs should be seen by the user in UI com.unraveldata.rbac.role.workspace1.data.user.filter=false ##Set to true if the user should also see apps that they run. com.unraveldata.rbac.role.workspace1.data.tags.filter=true ##Set to true if the user should also see apps with matching user tags. com.unraveldata.rbac.role.workspace1.data.field.queue=DBWkps1 ##Only app data with ‘queue = DBWkps1’ is shown to user. ##cluster_1_2 role config com.unraveldata.rbac.role.cluster_1_2.users= user2 ##Optional com.unraveldata.rbac.role.cluster_1_2.groups=GRP_B com.unraveldata.rbac.role.cluster_1_2.views=clusters.resources, clusters.chargeback, compute, jobs ##Set which tabs should be seen by the user in UI com.unraveldata.rbac.role.cluster_1_2.data.user.filter=false ##Set to true if the user should also see apps run by him com.unraveldata.rbac.role.cluster_1_2.data.tags.filter=true ##Set to true if the user should also see apps with matching user tags com.unraveldata.rbac.role.cluster_1_2.data.field.clusterUid=cluster1, cluster2 ##Only app data with “ clusterUid == cluster1 || cluster2 “ is shown to user ##workspace_cluster role config com.unraveldata.rbac.role.workspace_cluster.users= user3 ##Optional com.unraveldata.rbac.role.workspace_cluster.groups=GRP_C com.unraveldata.rbac.role.workspace_cluster.views=clusters.resources, clusters.chargeback, compute, jobs ##Set which tabs should be seen by the user in UI com.unraveldata.rbac.role.workspace_cluster.data.user.filter=false ##Set to true if the user should also see apps run by him com.unraveldata.rbac.role.workspace_cluster.data.tags.filter=true ##Set to true if the user should also see apps with matching user tags com.unraveldata.rbac.role.workspace_cluster.data.field.clusterUid=cluster3, cluster4 ##Only app data with “ clusterUid == cluster3 || cluster4 “ is shown to user com.unraveldata.rbac.role.workspace_cluster.data.field.queue=‘DBWkps2’ ##Only app data with “ queue == DBWkps2“ is shown to user
Create a role with rbac_clusters and rbac_workspaces tag:
com.unraveldata.rbac.roles=cw com.unraveldata.rbac.role.cw.groups=group1,group2,group3,.. com.unraveldata.rbac.role.cw.data.field.clusterUid=$tags.rbac_clusters com.unraveldata.rbac.role.cw.data.field.queue=$tags.rbac_workspaces
User tagging script
Input file:
clusters-workspaces_groups.csv
Input file content:
Clusters;Workspaces;Groups ala;;ux-rg-bd-scealadlbiro-dev bda;;ux-rg-bd-bigdataadmins db467450-0523-4919-81c3-1f18f6937246;;dummy-group12,dummy-group10 ;root.users.user6,root.users.user7;dummy-group12
Script file content:
const fs = require('fs'); const path = require('path'); const CWGroupsCSVPath = path.join(__dirname, 'clusters-workspaces_groups.csv'); function union(arr1, arr2) { const arr = []; const obj = {}; for (let i = 0; i < arr1.length; i += 1) { arr.push(arr1[i]); obj[arr1[i]] = true; } for (let i = 0; i < arr2.length; i += 1) { if (!obj[arr2[i]]) { arr.push(arr2[i]); } } return arr; } const groupsClustersMap = {}; const groupsWorkspacesMap = {}; function getGroupsCWMap() { let fd; try { fd = fs.openSync(CWGroupsCSVPath, 'r'); } catch (err) { console.error( 'RBAC : could not open rbac_queues_groups.csv file; file path =', CWGroupsCSVPath ); console.error(err); return {}; } try { const txt = fs.readFileSync(fd, 'utf-8'); if (typeof txt === 'string' && txt.length > 0) { const lines = txt.trim().split(/\r?\n/); for (let i = 1; i < lines.length; i += 1) { const line = lines[i]; const cwGroups = line.split(';'); const clusters = cwGroups[0].split(','); const workspaces = cwGroups[1].split(','); const groups = cwGroups[2].split(','); const formattedClusters = []; const formattedWorkspaces = []; const formattedGroups = []; for (let j = 0; j < clusters.length; j += 1) { const formattedCluster = clusters[j].trim().toLowerCase(); if (formattedCluster) { formattedClusters.push(formattedCluster); } } for (let j = 0; j < workspaces.length; j += 1) { const formattedWorkspace = workspaces[j].trim().toLowerCase(); if (formattedWorkspace) { formattedWorkspaces.push(formattedWorkspace); } } for (let j = 0; j < groups.length; j += 1) { const formattedGroup = groups[j].trim().toLowerCase(); if (formattedGroup) { formattedGroups.push(formattedGroup); } } for (let j = 0; j < formattedGroups.length; j += 1) { const formattedGroup = formattedGroups[j]; if (groupsClustersMap[formattedGroup]) { groupsClustersMap[formattedGroup] = union( groupsClustersMap[formattedGroup], formattedClusters ); } else { groupsClustersMap[formattedGroup] = formattedClusters; } if (groupsWorkspacesMap[formattedGroup]) { groupsWorkspacesMap[formattedGroup] = union( groupsWorkspacesMap[formattedGroup], formattedWorkspaces ); } else { groupsWorkspacesMap[formattedGroup] = formattedWorkspaces; } } } } return groupsCWMap; } catch (err) { console.error('RBAC : could not create Groups Queues Map.'); console.error(err); return {}; } finally { fs.closeSync(fd); } } getGroupsCWMap(); console.log('RBAC : Groups Clusters Map -', JSON.stringify(groupsClustersMap)); console.log('RBAC : Groups Workspaces Map -', JSON.stringify(groupsWorkspacesMap)); function getTags(username, userGroups) { const tags = {}; if ( ( Object.keys(groupsWorkspacesMap).length === 0 && Object.keys(groupsClustersMap).length === 0 ) || !Array.isArray(userGroups) || userGroups.length === 0 ) { return tags; } let rbac_workspaces = []; let rbac_clusters = []; for (let i = 0; i < userGroups.length; i += 1) { const userGroup = userGroups[i].toLowerCase(); const workspaces = groupsWorkspacesMap[userGroup]; const clusters = groupsClustersMap[userGroup]; if (workspaces && workspaces.length > 0) { rbac_workspaces = union(rbac_workspaces, workspaces); } if (clusters && clusters.length > 0) { rbac_clusters = union(rbac_clusters, clusters); } } if (rbac_clusters.length > 0) { tags.rbac_clusters = rbac_clusters; } if (rbac_workspaces.length > 0) { tags.rbac_workspaces = rbac_workspaces; } return tags; } module.exports = getTags;
Example 3
You have a map of queues to groups, where users of a group can access the data with queues belonging to the possible queues of the respective group.
com.unraveldata.rbac.roles=role1, role2,.. com.unraveldata.rbac.role.role1.users= user1 ##Optional com.unraveldata.rbac.role.role1.groups=G1 com.unraveldata.rbac.role.role1.views=clusters.resources, clusters.chargeback, compute, jobs ##Set the tabs that must be seen by the user on the UI. com.unraveldata.rbac.role.role1.data.user.filter=false ##Set to true if the user should also see apps run by them. com.unraveldata.rbac.role.role1.data.tags.filter=true ##Set to true if the user should also see apps with matching user tags. com.unraveldata.rbac.role.role1.data.field.queue=Q1, Q2 ##Only app data with ‘queue = Q1 || Q2 “ is shown to user.
Create a role with rbac_queue tag:
com.unraveldata.rbac.roles=rq com.unraveldata.rbac.role.rq.groups=group1,group2,group3,.. com.unraveldata.rbac.role.rq.data.field.queue=$tags.rbac_queue
User tagging script
Input file:
rbac_queues_groups.csv
Input file content:
Queue Names;Group Name ala;ux-rg-bd-scealadlbiro-dev bda;ux-rg-bd-bigdataadmins root.users.user6;dummy-groups06,dummy-group12 root.users.user7;dummy-group12
Script file content:
const fs = require('fs'); const path = require('path'); const CSV_FILE_NAME = 'rbac_queues_groups.csv'; const CSV_FILE_PATH = path.join(__dirname, CSV_FILE_NAME); function union(arr1, arr2) { const arr = []; const obj = {}; for (let i = 0; i < arr1.length; i += 1) { arr.push(arr1[i]); obj[arr1[i]] = true; } for (let i = 0; i < arr2.length; i += 1) { if (!obj[arr2[i]]) { arr.push(arr2[i]); } } return arr; } function getGroupsQueuesMap() { let fd; const groupsQueuesMap = {}; try { fd = fs.openSync(CSV_FILE_PATH, 'r'); } catch (err) { console.error( 'RBAC : could not open rbac_queues_groups.csv file; file path =', CSV_FILE_PATH ); console.error(err); return {}; } try { const txt = fs.readFileSync(fd, 'utf-8'); if (typeof txt === 'string' && txt.length > 0) { const lines = txt.trim().split(/\r?\n/); for (let i = 1; i < lines.length; i += 1) { const line = lines[i]; const queuesGroups = line.split(';'); const queues = queuesGroups[0].split(','); const groups = queuesGroups[1].split(','); const formattedQueues = []; const formattedGroups = []; for (let j = 0; j < queues.length; j += 1) { const formattedQueue = queues[j].trim().toLowerCase(); if (formattedQueue) { formattedQueues.push(formattedQueue); } } for (let j = 0; j < groups.length; j += 1) { const formattedGroup = groups[j].trim().toLowerCase(); if (formattedGroup) { formattedGroups.push(formattedGroup); } } for (let j = 0; j < formattedGroups.length; j += 1) { const formattedGroup = formattedGroups[j]; if (groupsQueuesMap[formattedGroup]) { groupsQueuesMap[formattedGroup] = union( groupsQueuesMap[formattedGroup], formattedQueues ); } else { groupsQueuesMap[formattedGroup] = formattedQueues; } } } } return groupsQueuesMap; } catch (err) { console.error('RBAC : could not create Groups Queues Map.'); console.error(err); return {}; } finally { fs.closeSync(fd); } } const groupsQueuesMap = getGroupsQueuesMap(); console.log('RBAC : Groups Queues Map -', JSON.stringify(groupsQueuesMap)); function getTags(username, userGroups) { const tags = {}; if ( Object.keys(groupsFIdsMap).length === 0 || !Array.isArray(userGroups) || userGroups.length === 0 ) { return tags; } let rbac_queue = []; for (let i = 0; i < userGroups.length; i += 1) { const userGroup = userGroups[i].toLowerCase(); const queues = groupsQueuesMap[userGroup]; if (queues && queues.length > 0) { rbac_queue = union(rbac_queue, queues); } } if (rbac_queue.length > 0) { tags.rbac_queue = rbac_queue; } return tags; } module.exports = getTags;