Ability to generate public URLs for dashboards with fixed (and hidden) global parameters


#1

Hi,

We would like to be able to generate dashboards to be embedded in customer pages (on our website), when the dashboard is given the customer ID as a global parameter. Customers should never see other customers’ data.

To do this effectively we require the following features:

  • That the public URL can be generated with pre-set global parameters encoded in the URL

  • That these can be generated from an API call programatically (i.e sent the dashboard ID and parameter value, return the encoded public URL).

  • That the page linked to by this URL does not have the global parameters visible or accessible to change (this could be an option sent in the API call).

I’m familiar with Python (and a little with Flask) and quite happy to help implement these (at least at the API level for now, they needn’t appear in the Web page option for generating the public dashboard URL right away).

How are the public dashboard URLs generated at the moment? Is it hashed and then stored in the database as a hash : dashboard lookup, or is it encrypted and then decrypted by the server on the fly to lookup the dashboard?

Also, is this process applied to the URL/dashboard ID + parameters or is the whole dashboard seralised and then hashed or encrypted (in the former case, we wouldn’t need to regenerate the public URLs if we change a graph on the dashboard for example).

Many thanks,
James McMurray


#2

Hi @jamesmcm,

Thank you for starting this discussion.

Currently parameters work by using the query text as a template and merging the parameters values into it when running the query. This is not safe and prone to SQL injections (by definition). For this reason we don’t support parameters in embeds or shared dashboards.

The use case you describe is a bit different, as you want to preset the parameters values, which makes the threat of SQL injections irrelevant as the person who assigns the parameter values is a trusted person who has access to the data.

The way share dashboards work is that we create an API Key object that has access to a given dashboard:

So this is how we currently generate a shared dashboard URL.

To bind a shared dashboard URL with a list of parameters we have two options (I can think of):

  1. We can store along with the API Key a list of parameter values that are allowed to be used with this API Key.
  2. Have the concept of a public API key and a private one. The public API key will be used to reference the dashboard and as a way of creating a random URL. The private API key will be known only to the system and will be used to sign the URL with a specific set of parameters.

The benefit of #1 is its simplicity and security (no way for an outside user to alter the list of values). The benefit of #2 is that we don’t have to create a database record for each set of parameters.

The next issue is how to load the data. Currently the public dashboard API returns the dashboard data along with the query results in one API call. To be able to run queries with parameters and utilize current APIs it’s best if we implement support in current Query Results API to deduce whether the current call is allowed based on the dashboard API key = if the dashboard has this query & the parameters are in the allowed list.


That’s a lot of text :slight_smile: I hope it all makes sense, please let me know if you have further questions and what are your thoughts.


#3

Thanks! Option 1 would work, so we could generate these URLs with fixed parameter settings via the API, and attempting to change those from the dashboard would result in an error (but they would still be visible in the UI) ?

That would be perfect, the only other thing is that we might want some separate filters on the dashboard, i.e. for date ranges, with default values set that can be modified by the anonymous public user. Would that be possible in combination with your proposal?


#4

I think that preset parameters won’t be rendered, so the user won’t even have the option to change them (or know they exist).

Eventually we want this to be possible, but that requires a more complete solution to the issue of allowing safely running parameterized queries by non trusted users.


#5

What about escaping the input, so no SQL statements could get passed? Here’s some additional ideas: https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet

Another idea would be to provide a regex filter for allowed params. That way you could have a date field , email address field, domain name field, etc. that gets checked against a whitelist regex filter. If it matches, its passed through, otherwise its rejected.

  • Ciaran

#6

Hi,

what an interesting discussion.

We really appreciate readash search and query capabilities.
I work for an environmental NGO and I use Redash to create dashboards related to physicochemical parameters of French Mediterranean lagoons (about 100) from 2010 to now.

I need to share my dashboard with 40 people, with only their own lagoons and ponds.
Actually I can’t do that because even i I can, as connected user, set parameters using dashboard widget, when I share the dashboard by url, the final reader will see another result…

So I think this would be a great feature.
As the possibility to support parameters in embeds or shared dashboards !


#7

This puts the responsibility on the user, which in many cases might not be fully aware of the possible risks.

But regardless of the security aspect adding the option to validate the input content (along with some presets for common patterns) is a good idea.


#8

Why not create them “proper” users instead of giving them shared dashboards? I would assume that you wouldn’t mind that they see data about the other ponds/lagoons, or would you?


#9

In fact it is a “problem”, not a huge one but a problem. I agree they could connect to the server, choose the dashboard and filter but it is not as easy to use" as it could be and by the way they don’t really want to see all their data.
Another way should consist to use a “connected_user_email” parameter in the query tool so the data would be filter.
Thanks for your attention and thanks for the work !


#10

Wanted to add a “+1” to this conversation and confirm that the scenario of selecting from set of predefined parameters would also work for our scenario: dashboards that are the same reports but varying by location, integrating the visualization into a product flow.

This ability would make redash particularly suitable for those of us that want an unopinioned BI/Reporting system that we can use as a data visualization extension of our products.

However, we do not have quite as strong a security requirement. For us this is just a convenience method for presenting slices of public-ish data.

We could make either option 1 or option 2 work (i.e. we could make a call with a private key to generate a secure token that could be used in a “signature check of the parameter” assuming that is what you meant). Proposal 2 sounds to me like s3 presigned urls conceptually: https://docs.aws.amazon.com/AmazonS3/latest/dev/ShareObjectPreSignedURL.html (Which reminds me you could probably include an expiry timestamp if you want a concept of a “session duration” )

FWIW: I feel that, for many users, you could also make the case that it was appropriate due diligence from a security standpoint to just sanitize everything that comes in over the query string. This would protect the data source itself, and, would just require the person generating the dashboard share string to have a some understanding of the data. To deal with the original scenario of customers not seeing each others data the data itself could use “crypto unique” or “unguessable” id space for the customer ids. Which I think is almost equivalent because the proposals above still produce a URL that is “valid forever” (unless you add the timestamp). So maybe separate the concerns of sql injection from the concerns of access authorization.