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;