Permissioning & Relations with Redshift

Anyone have any resources on best practices for managing permissions in redshift with DBT. In particular I’m thinking through the right way to structure VIEWs if I don’t want analysts to have access to the underlying table. Do we just materialize them anyway? Do we use ephemeral relations?

Generally, all users are in groups, and groups are GRANTed permissions using post-hooks in DBT. You can easily write a macro to cycle through those grants (see below for an example).

Specific to your question, allowing someone to SELECT from a view does not allow them to SELECT the underlying table(s) directly. They will need USAGE permissions on the tables, but not SELECT.

{% macro grant_usage_on_all_schemas_to(user_list) %}
  {# CALL THIS MACRO WITH THE FOLLOWING SYNTAX:
    on-run-end:
        - '{{ grant_usage_on_all_schemas_to(["group readers", "group transformers"]) }}'
  #}
  {%- call statement('get_all_schemas', fetch_result=True, auto_begin=False) -%}

    select distinct
      nspname as schema_name
    from pg_namespace
    where
      schema_name not like 'pg_%'
      and schema_name not like 'dbt_%'

  {%- endcall -%}

  {% set result = load_result('get_all_schemas') %}
  {% set schema_list = result['data'] | map(attribute=0) | list %}

  {% for u in user_list %}
    {% for s in schema_list %}
      grant usage on schema {{ s }} to {{ u }} ;
    {% endfor %}
  {% endfor %}

{% endmacro %}

{% macro grant_select_on_all_tables_in(schema_list, user_list) %}
  {# CALL THIS MACRO WITH THE FOLLOWING SYNTAX:
    on-run-end:
        - '{{ grant_select_on_all_tables_in(["analytics"],["group readers","group transformers"]) }}'
  #}
  {% for u in user_list %}
    {% for s in schema_list %}
      grant select on all tables in schema {{ s }} to {{ u }} ;
    {% endfor %}
  {% endfor %}

{% endmacro %}

{% macro grant_execute_on_all_functions_in(schema_list, user_list) %}
  {# CALL THIS MACRO WITH THE FOLLOWING SYNTAX:
    on-run-end:
        - '{{ grant_execute_on_all_functions_in(["analytics"],["group readers","group transformers"]) }}'
  #}
  {% for u in user_list %}
    {% for s in schema_list %}
      grant execute on all functions in schema {{ s }} to {{ u }} ;
    {% endfor %}
  {% endfor %}

{% endmacro %}
4 Likes

The “usage without select” is exactly the trick I was looking for. Thank you!

Also thanks for this macro – super helpful!