Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for roles in grants #259

Merged
merged 21 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
tests for roles granting
  • Loading branch information
bcmeireles committed Jan 24, 2025
commit b9fd66e62a1c6379e24cfd1e27103c2b62ae357d
2 changes: 2 additions & 0 deletions .github/scripts/create_env_file.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ DREMIO_DATABASE=dbt_test
DBT_TEST_USER_1=dbt_test_user_1
DBT_TEST_USER_2=dbt_test_user_2
DBT_TEST_USER_3=dbt_test_user_3
DBT_TEST_ROLE_1=dbt_test_role_1
DBT_TEST_ROLE_2=dbt_test_role_2
EOF

echo ".env file created successfully."
1 change: 0 additions & 1 deletion tests/functional/adapter/grants/base_grants.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from tests.utils.util import BUCKET


@pytest.mark.skip(reason="Dremio only supports grants in EE/DC editions.")
class BaseGrantsDremio(BaseGrants):
# This is overridden to change insert privilege to alter
def privilege_grantee_name_overrides(self):
Expand Down
170 changes: 168 additions & 2 deletions tests/functional/adapter/grants/test_model_grants.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import pytest
import pytest, os

from dbt.tests.adapter.grants.test_model_grants import (
BaseModelGrants,
Expand All @@ -31,14 +31,101 @@
from tests.functional.adapter.grants.base_grants import BaseGrantsDremio
from tests.utils.util import relation_from_name

role_model_schema_yml = """
version: 2
models:
- name: my_model
config:
grants:
select: ["role:{{ env_var('DBT_TEST_ROLE_1') }}"]
"""

role2_model_schema_yml = """
version: 2
models:
- name: my_model
config:
grants:
select: ["role:{{ env_var('DBT_TEST_ROLE_2') }}"]
"""

table_role_model_schema_yml = """
version: 2
models:
- name: my_model
config:
materialized: table
grants:
select: ["role:{{ env_var('DBT_TEST_ROLE_1') }}"]
"""

role2_table_model_schema_yml = """
version: 2
models:
- name: my_model
config:
materialized: table
grants:
select: ["role:{{ env_var('DBT_TEST_ROLE_2') }}"]
"""

multiple_roles_table_model_schema_yml = """
version: 2
models:
- name: my_model
config:
materialized: table
grants:
select: ["role:{{ env_var('DBT_TEST_ROLE_1') }}", "role:{{ env_var('DBT_TEST_ROLE_2') }}"]
"""

multiple_privileges_role_table_model_schema_yml = """
version: 2
models:
- name: my_model
config:
materialized: table
grants:
select: ["role:{{ env_var('DBT_TEST_ROLE_1') }}"]
insert: ["role:{{ env_var('DBT_TEST_ROLE_2') }}"]
"""

users_and_roles_model_schema_yml = """
version: 2
models:
- name: my_model
config:
grants:
select: ["role:{{ env_var('DBT_TEST_ROLE_1') }}", "user:{{ env_var('DBT_TEST_USER_1') }}", "user:{{ env_var('DBT_TEST_USER_2') }}"]
insert: ["role:{{ env_var('DBT_TEST_ROLE_2') }}", "user:{{ env_var('DBT_TEST_USER_3') }}"]
"""

users_and_roles_table_model_schema_yml = """
version: 2
models:
- name: my_model
config:
materialized: table
grants:
select: ["role:{{ env_var('DBT_TEST_ROLE_1') }}", "user:{{ env_var('DBT_TEST_USER_1') }}", "user:{{ env_var('DBT_TEST_USER_2') }}"]
insert: ["role:{{ env_var('DBT_TEST_ROLE_2') }}", "user:{{ env_var('DBT_TEST_USER_3') }}"]
"""

@pytest.mark.skip(reason="Dremio only supports grants in EE/DC editions.")
class TestViewGrantsDremio(BaseGrantsDremio, BaseModelGrants):
def get_test_roles(self):
test_roles = []
for env_var in ["DBT_TEST_ROLE_1", "DBT_TEST_ROLE_2"]:
role_name = os.getenv(env_var)
if role_name:
test_roles.append(role_name)
return test_roles

# Overridden to only include view materialization
def test_view_table_grants(self, project, get_test_users):
# we want the test to fail, not silently skip
test_users = get_test_users
test_roles = self.get_test_roles()
select_privilege_name = self.privilege_grantee_name_overrides()["select"]
assert len(test_users) == 3

Expand All @@ -51,14 +138,42 @@ def test_view_table_grants(self, project, get_test_users):
expected = {select_privilege_name: [test_users[0]]}
assert model.config.grants == expected
assert model.config.materialized == "view"
expected = {select_privilege_name: ["user:" + test_users[0]]}
self.assert_expected_grants_match_actual(project, "my_model", expected)

# View materialization, change select grant user
updated_yaml = self.interpolate_name_overrides(user2_model_schema_yml)
write_file(updated_yaml, project.project_root, "models", "schema.yml")
(results, log_output) = run_dbt_and_capture(["--debug", "run"])
assert len(results) == 1
expected = {select_privilege_name: [get_test_users[1]]}
expected = {select_privilege_name: ["user:" + get_test_users[1]]}
self.assert_expected_grants_match_actual(project, "my_model", expected)

# roles
updated_yaml = self.interpolate_name_overrides(role_model_schema_yml)
write_file(updated_yaml, project.project_root, "models", "schema.yml")
(results, log_output) = run_dbt_and_capture(["--debug", "run"])
assert len(results) == 1
expected = {select_privilege_name: ["role:" + test_roles[0]]}
self.assert_expected_grants_match_actual(project, "my_model", expected)

updated_yaml = self.interpolate_name_overrides(role2_model_schema_yml)
write_file(updated_yaml, project.project_root, "models", "schema.yml")
(results, log_output) = run_dbt_and_capture(["--debug", "run"])
assert len(results) == 1
expected = {select_privilege_name: ["role:" + test_roles[1]]}
self.assert_expected_grants_match_actual(project, "my_model", expected)

updated_yaml = self.interpolate_name_overrides(users_and_roles_model_schema_yml)
write_file(updated_yaml, project.project_root, "models", "schema.yml")
(results, log_output) = run_dbt_and_capture(["--debug", "run"])
assert len(results) == 1
insert_privilege_name = self.privilege_grantee_name_overrides()["insert"]
expected = {
select_privilege_name: ["role:" + test_roles[0], "user:" + get_test_users[0],
"user:" + get_test_users[1]],
insert_privilege_name: ["role:" + test_roles[1], "user:" + get_test_users[2]],
}
self.assert_expected_grants_match_actual(project, "my_model", expected)


Expand All @@ -76,9 +191,18 @@ def get_grants_on_relation(self, project, relation_name):
actual_grants = adapter.standardize_grants_dict(grant_table)
return actual_grants

def get_test_roles(self):
test_roles = []
for env_var in ["DBT_TEST_ROLE_1", "DBT_TEST_ROLE_2"]:
role_name = os.getenv(env_var)
if role_name:
test_roles.append(role_name)
return test_roles

# Overridden to only include table materializations
def test_view_table_grants(self, project, get_test_users):
test_users = get_test_users
test_roles = self.get_test_roles()
select_privilege_name = self.privilege_grantee_name_overrides()["select"]
insert_privilege_name = self.privilege_grantee_name_overrides()["insert"]
assert len(test_users) == 3
Expand Down Expand Up @@ -133,3 +257,45 @@ def test_view_table_grants(self, project, get_test_users):
insert_privilege_name: ["user:" + test_users[1]],
}
self.assert_expected_grants_match_actual(project, "my_model", expected)

# roles
updated_yaml = self.interpolate_name_overrides(table_role_model_schema_yml)
write_file(updated_yaml, project.project_root, "models", "schema.yml")
(results, log_output) = run_dbt_and_capture(["--debug", "run"])
assert len(results) == 1
expected = {select_privilege_name: ["role:" + test_roles[0]]}
self.assert_expected_grants_match_actual(project, "my_model", expected)

updated_yaml = self.interpolate_name_overrides(role2_table_model_schema_yml)
write_file(updated_yaml, project.project_root, "models", "schema.yml")
(results, log_output) = run_dbt_and_capture(["--debug", "run"])
assert len(results) == 1
expected = {select_privilege_name: ["role:" + test_roles[1]]}
self.assert_expected_grants_match_actual(project, "my_model", expected)

updated_yaml = self.interpolate_name_overrides(multiple_roles_table_model_schema_yml)
write_file(updated_yaml, project.project_root, "models", "schema.yml")
(results, log_output) = run_dbt_and_capture(["--debug", "run"])
assert len(results) == 1
expected = {select_privilege_name: ["role:" + test_roles[0], "role:" + test_roles[1]]}
self.assert_expected_grants_match_actual(project, "my_model", expected)

updated_yaml = self.interpolate_name_overrides(multiple_privileges_role_table_model_schema_yml)
write_file(updated_yaml, project.project_root, "models", "schema.yml")
(results, log_output) = run_dbt_and_capture(["--debug", "run"])
assert len(results) == 1
expected = {
select_privilege_name: ["role:" + test_roles[0]],
insert_privilege_name: ["role:" + test_roles[1]],
}
self.assert_expected_grants_match_actual(project, "my_model", expected)

updated_yaml = self.interpolate_name_overrides(users_and_roles_table_model_schema_yml)
write_file(updated_yaml, project.project_root, "models", "schema.yml")
(results, log_output) = run_dbt_and_capture(["--debug", "run"])
assert len(results) == 1
expected = {
select_privilege_name: ["role:" + test_roles[0], "user:" + get_test_users[0], "user:" + get_test_users[1]],
insert_privilege_name: ["role:" + test_roles[1], "user:" + get_test_users[2]],
}
self.assert_expected_grants_match_actual(project, "my_model", expected)
Loading