Data Security

Allowing Only Tableau Vizes with Unrestricted Trusted Authentication, SAML or OIDC

Editor’s Note: Huge thanks to Robin Cottiss who helped me navigate the world of authentication in Tableau as he has for so many years to be able to write this. He doesn’t have the same online presence as a lot of other Tableau wizards but I can’t say how much of my and others Tableau knowledge that is out there has either been guided by or just a straight repackaging of the hard-gained work Robin has put in.

When embedding Tableau vizes for external use, the three most common SSO mechanisms are Trusted Authentication, SAML, and OpenID Connect (OIDC).

Trusted Authentication or Trusted Tickets has two modes, which are set as server-level flags:

  • Restricted (default): A user can only see Vizes, and cannot see the full Tableau Server UI.
  • Unrestricted: Redeeming the ticket creates a full session to Tableau Server, and the user can see the full Tableau Server UI

SAML and OpenID Connect always create a full session, so they work like Unrestricted Tickets.

Additionally, Restricted Trusted Tickets (the default Trusted Authentication mode) also disables:

  • Custom Views
  • Subscriptions
  • Alerts
  • Other interactions with Web Edit, Ask Data, etc.

Many customers would prefer to have a session started with any of the three SSO mechanisms, that allows all the Viz features, but doesn’t let the user ever get to the full Tableau Server UI. Is it possible?

(more…)

Attribute-Based Row Level Security in Tableau, a Working Technique

Tableau has the most flexibility for doing Row Level Security filtering using what is termed the “Standard Method”: a JOIN between a Data Table and an Entitlements table. The basic assumption, as seen in the RLS Whitepaper, is that this Entitlements table exists in the same database at the Data Table. This is a very narrow assumption, that is only true for a small subset of real deployments.

In many environments and applications, there is no “Entitlements” table within the same logical database as the Data table. In fact, there may be no “Entitlements table” that can be reached at all — entitlements can be retrieved somehow, but they may be in any number of forms.

The most common request I see is to pass a set of Attributes (lists or arrays) of values directly into a Tableau report at run-time. The rest of the post will describe a flexible and generic method for making this possible in a secure way. It builds upon the baseline of the PostgreSQL/Python environment in the using a Web Service as a Data Source post, but is even simpler.

(more…)

Passing a JWT as a Tableau Parameter

You’re probably aware that Tableau Parameters are not an inherently secure way to filter down data. A lot of people are using JWTs to pass around tokens with security entitlements, so if you are good with that, did you know you can pass one right into a Tableau Parameter?

I’ve built out an example where the JWT comes through then a function fires off a web service request, as part of the work for using a Web Service / REST API as a live data source, but there’s no reason you couldn’t build a smaller function for processing the JWT and then use just that in Custom SQL in Tableau when building your data source.

Although the following example uses PostgreSQL (and PL/Python), you could theoretically implement this in any language with access to a language that can process JWT. In MS SQL Server, a CLR Stored Procedure can access C# functionality, and the Systems.IdentityModel.Tokens.Jwt namespace appears to have all the necessary functionality to implement a very similar workflow.

Below I’ll work through a workflow using PL/Python on PostgreSQL — again, the same concept could be implemented on any RDBMS with functions.

(more…)

Web Services / REST APIs as a Data Source in Tableau: A PostgreSQL/Python solution

The trend toward wrapping together data and security filtering into RESTful web services has only increased in the past few years, and for a lot of good reasons. If the REST API is optimized to return very quickly based on a set of filtering parameters, the performance alone can justify the architecture. However, Tableau is planning to do more with the result set than simply display it directly — Tableau is ready to do deep analysis and discover new insights. Because of this, Tableau’s VizQL engine needs something it can query in many different ways as the basis for a data source connection.

How can we bridge the gap between a JSON (or XML, if anyone still does that) object response and a relational query engine?

What if I told you THIS was all that was necessary on the Tableau Desktop side to build a data source that acts as a “live” connection to a web service?:

Accessing the PL/Python Function in Tableau

Custom SQL in Tableau

Connect to the PostgreSQL database in Tableau Desktop using whatever credentials you created for an end user.

Then on the Data Connection screen, you’ll find onĀ New Custom SQL on the left:

If you drag that out, then the dialog to define the Custom SQL query appears:

Custom SQL dialog

As you can see, the query is just SELECT * FROM function_name( arguments ), with whatever parameters you want to attach. You can create new parameters right from this dialog box, then put them in place. Make sure to give sensible defaults, and probably most should default to an empty string so that someone can only access if they have the right tokens / etc.

How is this possible?

There’s a whole lot of setup on the PostgreSQL side, but the payoff is the simplicity of the setup in Tableau.

The solution is based on the architecture originally laid out here, but I’ve put together a Dockerfile which builds out a PostgreSQL database ready for your custom set of functions which will dynamically call a RESTful Web Service based on Tableau’s parameters.

(more…)

The Missing Link – Putting a Hyper File from the Hyper API into a TDSX or TWBX File

The Tableau Hyper API is an amazingly powerful tool for building out Extracts that, for whatever reason, cannot be built or maintained using the standard Tableau Server extract refresh process. You can publish a Hyper file directly to a Tableau Server, but there are several drawbacks:

  • Tableau Server will build out an automatic TDS file, taking a rough guess at any type of metadata categorization (Measure vs. Dimensions, Hierarchies, Geographic info, etc.)
  • The only use for this data source will be creating Ad Hoc reports using Web Edit (or hoping someone in Desktop now knows that it exists). You can’t integrate it easily in an existing Workbook
  • It only works with Single-Table Extracts, and in older versions of Tableau, the single table must be named “Extract” or you will encounter errors.

What is missing is a TDS file to pair up with the Hyper file, describing the exact metadata that you want to go along with the Extracted data. In this article, I’ll describe a workflow that result in a fully controlled TDSX file with a newly generated Hyper file.

(more…)

Multiple Table (Normalized) Hyper Extracts

Starting in Tableau 2018.3+:

  • The design for row level security will be the same in both live connections and extracts
  • Extract files with security will create much faster
  • Best practices for entitlements tables are now feasible in Extracts

Let’s dig into the essentials and how we can make this work for effective Row Level Security.

(more…)

Defusing Row Level Security in Your Extracts (Before They Blow Up) Part Two

This documentation is for versions of Tableau prior to 2018.3

If you are using the 2018.3 version of Tableau or later, you’ll want to implement Row Level Security using Multi-Table Extracts and the “Standard” Method of Row Level Security. Read all about them at

How to set up your Database for Row Level Security in Tableau

If you are on a version prior to 2018.3, continue

EDITOR’S NOTE 2018-05-17: At the current time, it has been determined that the CONTAINS() solution below performs very poorly in the Hyper extract system in all releases of Tableau 10.5 and the 2018.1.0 release. The performance issues have been corrected in the 2018.1.1 release, but will not appear in any version of 10.5. If you are currently using it in a pre-10.5 version of Tableau, please only upgrade to 2018.1.1 and after.

In Part Two of the series (see Part One here), we’ll go through two solutions to Row Level Security that are a bit more programmatic and require some work outside of just Tableau Desktop calculations, but our often the recommended solution due to their speed and flexibility.

(more…)

Multi-Tenant Data Environments: Templates and Other Solutions

Update 2020-11-06: Rename this article to be more obvious and updated some of the code, along with learnings from the past few years.

Tableau can do Multi-Tenancy. But your database might also, in a variety of ways, also do what you think of as “multi-tenancy”.

In years having this discussion, I have learned one thing: Multi-Tenancy is used differently by everyone to describe these structural organizations. So we have to be very clear to make sure we all are talking about the same things. That makes this article a bit long-winded (surprising for me I know!), but hopefully the precision justifies the extra words.

If you are using Tableau to present data to multiple different organizations (customers, clients, suppliers, hospital groups etc.), the structure of how you store that data greatly affects the way you should organize content on Tableau Server.

Multi-Tenancy in Tableau Server: Sites or Hierarchical Projects

(more…)

How to set up your Database for Row Level Security in Tableau

Editor’s Note 2: There is a newer, simplified overview of just “how to make RLS work in Tableau” available now: Quick Explanation of Row Level Security in Tableau. This post and the whitepaper provide a more thorough explanation of “why” and how to set up your database.

Editor’s Note: The official (and improved) whitepaper version of this is available from Tableau here

The techniques outlined in this post are applicable to Live Connections and Multi-Table Extracts (available in Tableau 2018.3+). If you need to use Extracts and are on a version of Tableau prior to 2018.3, please see Keeping Your Extracts From Blowing Up .

(more…)