Skip to content

[CT-660] [Feature] Add Grant SQL to Global Project #5263

@nathaniel-may

Description

@nathaniel-may

Description

This is the second in a two ticket series. #5189 is the first ticket. They will be merged sequentially, but both are required for this feature to be exposed to users.

Today users often configure a post_hook to grant permissions on models, seeds, and snapshots:

{{ config(post_hook = 'grant select on {{ this }} to role reporter') }}

These two tickets aim to make it easier to specify grants allowing it to be configured directly both in dbt_project.yml as well as in source files:

# dbt_project.yml
models:
  export:
    +grants:
      select: ['reporter', 'bi']
-- SQL
{{ config(grants = {'select': ['other_user']}) }}

These grant configs will not necessarily look the same for each and every warehouse. The logic to generate the sql from these configs can be overriden by adapters.

Some complexity gets added when you consider that you cannot simply revoke all privileges from a table and apply the configured ones. This is because revoking all may also revoke dbt's ownership of the table, and because some warehouses require explicitly naming the grants to be removed. This implementation reads the grants first, then constructs a minimal revoke and grant statement from the resulting diff.

Implementation

  • create a new macro in the global project: get_show_grant_sql(relation: Relation) -> str that retrieves grant information for that model. The default implementation should return a string in the form "show grants on table dbt_jcohen.whatever"
  • create a new macro in the global project: get_grant_sql(relation: Relation, grant_config: dict) -> str that creates the warehouse-specific sql from grant portion of the config. Since it will be common, the default implementation should return grant <privilege> on <relation.type> <relation> to <recipients>. Warehouses that deviate from this can override. Use dispatch pattern (dbt docs) with a default__ to enable this. The macro signature here is designed to accept different shapes of grant configs for each adapter to use whatever best fits the warehouse's permissions system.
  • create a new macro called get_revoke_sql that takes a relation, and a grant config dict and returns a string in the form f"revoke {grant_config.privilege} on {relation} from {grant_config.recipients}". The grant config will contain multiple priv-recipient mappings.
  • create a new macro in the global project: apply_grants which takes 3 parameters: revoke: Bool, relation: Relation, grant_config: dict and returns None. It calls get_show_grant_sql to determine what grants are currently applied, and uses grant config to determine what grants need to be revoked, and which grants need to be granted. If the revoke param is True, get_revoke_sql is called, then get_grant_sql with a new dictionary representing the diff to apply the grants. (see persist_docs for an example of similar implementation). This should be overridable by adapters so use the dispatch pattern (dbt docs) with a default__ to enable this. For a complete example see @jtcohen6's comment below.
  • add a call to apply_grants(..., revoke=True) in all materializations. This includes incremental models, seeds, and snapshots even though it will usually not be necessary. Users can override if they come across a special case where they need to.
  • [CT-808] Add "adapter zone" tests for grants #5437
    • test that projects can define grants in 1) the dbt_project.yml, 2) models, seeds, and snapshots, and 3) both the dbt_project.yml and models, seeds, and snapshots and those permissions can be read back directly from the postgres warehouse after a run.
    • test two subsequent runs (dbt build && dbt build) with: same grants; additional grants in second run; fewer grants in second run. Confirm that the final set of grants matches the final configured set of grants in all cases.
  • test a model that has preexisting grants, and does not have grants configured. dbt should leave it be, and not run any show/revoke/grant statements.

Adapters

Links for your convenience. These do not need to be completed to close out the ticket.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestgrantsIssues related to dbt's grants functionality

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions