Skip to content

Commit

Permalink
remove database roles when standardizing the grants dict so that dbt-…
Browse files Browse the repository at this point in the history
…snowflake does not attempt to revoke them
  • Loading branch information
mikealfare committed Sep 27, 2024
1 parent fdc2630 commit ee6f9bb
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 8 deletions.
2 changes: 1 addition & 1 deletion dbt/adapters/snowflake/impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ def standardize_grants_dict(self, grants_table: "agate.Table") -> dict:
grantee = row["grantee_name"]
granted_to = row["granted_to"]
privilege = row["privilege"]
if privilege != "OWNERSHIP" and granted_to != "SHARE":
if privilege != "OWNERSHIP" and granted_to not in ["SHARE", "DATABASE_ROLE"]:
if privilege in grants_dict.keys():
grants_dict[privilege].append(grantee)
else:
Expand Down
44 changes: 37 additions & 7 deletions tests/functional/auth_tests/test_database_role.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,68 @@
import os

import pytest

from dbt.tests.util import run_dbt


BLOCKING_DB_ROLE = "BLOCKING_DB_ROLE"
SEED = """
id
1
""".strip()


MODEL = """
{{ config(
materialized='incremental',
) }}
select * from {{ ref('my_seed') }}
"""


class TestDatabaseRole:
"""
This test addresses https://github.com/dbt-labs/dbt-snowflake/issues/1151
While dbt-snowflake does not manage database roles (it only manages account roles,
it still needs to account for them so that it doesn't try to revoke them.
"""

@pytest.fixture(scope="class")
def seeds(self):
return {"my_seed.csv": SEED}

@pytest.fixture(scope="class")
def models(self):
return {"my_table.sql": "{{ config(materialized='table') }} select 1 as id"}
return {"my_model.sql": MODEL}

@pytest.fixture(scope="class")
def project_config_update(self):
return {"models": {"+grants": {"select": [BLOCKING_DB_ROLE]}}}
# grant to the test role even though this role already has these permissions
# this triggers syncing grants since `apply_grants` first looks for a grants config
return {"models": {"+grants": {"select": [os.getenv("SNOWFLAKE_TEST_ROLE")]}}}

@pytest.fixture(scope="class", autouse=True)
def setup(self, project):
project.run_sql(f"CREATE DATABASE ROLE {BLOCKING_DB_ROLE}")
"""
Create a database role with access to the model we're about to create.
The existence of this database role triggered the bug as dbt-snowflake attempts
to revoke it if the user also provides a grants config.
"""
role = "BLOCKING_DB_ROLE"
project.run_sql(f"CREATE DATABASE ROLE {role}")
sql = f"""
GRANT
ALL PRIVILEGES ON FUTURE TABLES
IN DATABASE {project.database}
TO DATABASE ROLE {BLOCKING_DB_ROLE}
TO DATABASE ROLE {role}
"""
project.run_sql(sql)
yield
project.run_sql(f"DROP DATABASE ROLE {BLOCKING_DB_ROLE}")
project.run_sql(f"DROP DATABASE ROLE {role}")

def test_database_role(self, project):
run_dbt(["seed"])
run_dbt(["run"])
# run a second time to trigger revoke on an incremental update
# this originally failed, demonstrating the bug
run_dbt(["run"])
run_dbt(["run", "--full-refresh"])

0 comments on commit ee6f9bb

Please sign in to comment.