TSC Part 2: Permissions
Welcome back! ICYMI, Part One provided info for setting up your environment and getting your project hierarchy. Part two of this Tableau Server Client introduction will focus on a popular topic: project permissions. How can we automate this? A CSV file. Really.
Tableau and the granularity of permissions is only continuing to grow as new features are released. As business users request creation of new Project folders to host their content, we need to be able to enable them more quickly.
If you’re using an Active Directory sync and groups not specific to Tableau then this might be slightly more difficult, but still possible. For the sake of our example today, our projects will follow the standard laid out by Tableau’s Blueprint with a single PROD folder and a UAT folder on the same site. Only difference is the suffix of “ – UAT”. Similarly, our Group names have a consistent structure: “[Business Area] – [Role]”. Example:
HR – Viewers
HR – Developers
HR – Super Users
With a consistent naming structure we can base our permissions file on the role suffix – or everything after the final “ – “. The list of resources/content types, capabilities, and modes can be under the permission item. If we know the types of projects we have (by “stage”), roles, and the content types, capabilities, and modes then we can make a CSV or Excel file to use and rapidly deploy projects. An example of this is in our 2_projectPermissions folder of the git repo.
In Part 1 we ran a script to create our projects – now we need to do the same for groups:
python 0_setup/CreateGroups.py
Now let’s dive in to permissions. There are 5 key steps to this script:
Get Credentials
Get Groups
Get Projects
Assign permissions
Assign view rights to parent folder(s)
The first three should be very similar to what we’ve done previously where we use list comprehension to grab the relevant items. The latter two will require a bit more explaining.
Before we begin, it’s important to discuss the Default project permissions. Each site on your instance of Tableau Online/Server has this project and you can set some default permissions that will be replicated for all future projects. I never think we want “All Users” to have access to most projects, so we’ll simply Delete this rule:
Now, let’s get started.
Get Credentials
Use env file as outline in Part 1 of this series
Get Groups and Projects
As mentioned in the intro, we will assume the Groups have the same root name and similar for the Projects. This is pretty straightforward by using the rsplit function, however for the PROD folder we can do a direct comparison:
Now, how did we pass these values to the script? Checkout the argparse library. This wonderful library allows us to define arguments/parameters and pass them in.
After defining the arguments, we use parse_args() to assign the values. Then we can access these using args.grouproot and args.projectroot to pass into our functions.
To tell python how to run this script we just use these flags when running it such as:
python AssignPermissions.py -g HR -p “Human Resources”
Assign Permissions
Onto the core of this script: the assignPermissions function. We call this function by passing the list of groups and projects and then we need to load our permissions file using pandas.
Note: full list of how to refer to permissions with the API is here
As our new dataframe consists of words/strings, we need to convert the Capability and Mode columns to something TSC can interpret. Originally, I did this a lot more manually with a dictionary, but have since learned we can instead use python’s “eval” function within a “lambda” function:
Before iterating on our dataframe we need to identify the roles per each group and the stage per project (using the same rsplit function mentioned above). With the list of projects we can loop over our dataframe to identify the appropriate permissions per stage and group with a filter. Typically, we don’t iterate over a dataframe for speed/performance reasons, so we’ll find a better way.
Looking at the sample add_default_permission script we can see that we pass in a dictionary on Capability to Mode to update permissions. With this end goal, we can use a combination of dictionary comprehension and a group by function to generate what we need:
As you can see above, the “area” portion of this new dictionary is a tuple of role and object (content type) and is mapped to a dictionary of permissions. Perfect.
Now we can iterate over this dictionary, map the role to the respective Group item, and call the appropriate update method based on the content type:
Assign view rights to parent folder(s)
You will notice that when the content type is “Project” we call another function. This function is relatively straightforward in comparison and something you should be familiar with given these first two scripts. We can assume that if a user is added to a sub-folder (or sub-project) that they should also be given view permissions to the parent project(s) above it in the hierarchy. This allows the users to navigate through the “Explore” tab more easily. So, we pass the parent project ID to this function, add view rights, and loop over It until there are no more parent projects.
Now, provided you’re in the 2_projectPermissions folder, you can run the script we previously mentioned:
python AssignPermissions.py -g HR -p “Human Resources”
You should see the Groups be added to both Projects with appropriate permissions for the project, workbooks, and datasources. You can, of course, expand this to cover Flows, Metrics, etc. as needed and new features are added.
I hope this has been a good introduction to how you can streamline permissioning and decrease time in project creation!