diff --git a/docs/infra/snowflake.md b/docs/infra/snowflake.md index 1dfa30f3..c673c519 100644 --- a/docs/infra/snowflake.md +++ b/docs/infra/snowflake.md @@ -161,14 +161,15 @@ The **elt** module has the following configuration: | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.0 | -| [snowflake](#requirement\_snowflake) | ~> 0.61 | +| [snowflake](#requirement\_snowflake) | ~> 0.88 | ## Providers | Name | Version | |------|---------| -| [snowflake.accountadmin](#provider\_snowflake.accountadmin) | ~> 0.61 | -| [snowflake.useradmin](#provider\_snowflake.useradmin) | ~> 0.61 | +| [snowflake](#provider\_snowflake) | ~> 0.88 | +| [snowflake.accountadmin](#provider\_snowflake.accountadmin) | ~> 0.88 | +| [snowflake.useradmin](#provider\_snowflake.useradmin) | ~> 0.88 | ## Modules @@ -186,35 +187,35 @@ The **elt** module has the following configuration: | Name | Type | |------|------| -| [snowflake_database_grant.this](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/database_grant) | resource | +| [snowflake_grant_account_role.analytics_r_to_reader](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.analytics_r_to_reporter](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.analytics_rwc_to_transformer](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.loader_to_airflow](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.loader_to_fivetran](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.loader_to_sysadmin](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.loading_to_loader](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.logger_to_accountadmin](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.logger_to_sentinel](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.logging_to_logger](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.raw_r_to_reader](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.raw_r_to_transformer](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.raw_rwc_to_loader](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.reader_to_github_ci](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.reader_to_sysadmin](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.reporter_to_sysadmin](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.reporting_to_reader](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.reporting_to_reporter](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.transform_r_to_reader](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.transform_rwc_to_transformer](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.transformer_to_dbt](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.transformer_to_sysadmin](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_account_role.transforming_to_transformer](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_account_role) | resource | +| [snowflake_grant_privileges_to_account_role.imported_privileges_to_logger](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_privileges_to_account_role) | resource | | [snowflake_role.loader](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role) | resource | | [snowflake_role.logger](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role) | resource | | [snowflake_role.reader](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role) | resource | | [snowflake_role.reporter](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role) | resource | | [snowflake_role.transformer](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role) | resource | -| [snowflake_role_grants.analytics_r_to_reader](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.analytics_r_to_reporter](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.analytics_rwc_to_transformer](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.loader_to_airflow](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.loader_to_fivetran](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.loader_to_sysadmin](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.loading_to_loader](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.logger_to_accountadmin](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.logger_to_sentinel](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.logging_to_logger](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.raw_r_to_reader](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.raw_r_to_transformer](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.raw_rwc_to_loader](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.reader_to_github_ci](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.reader_to_sysadmin](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.reporter_to_sysadmin](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.reporting_to_reader](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.reporting_to_reporter](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.transform_r_to_reader](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.transform_rwc_to_transformer](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.transformer_to_dbt](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.transformer_to_sysadmin](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | -| [snowflake_role_grants.transforming_to_transformer](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | | [snowflake_user.airflow](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/user) | resource | | [snowflake_user.dbt](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/user) | resource | | [snowflake_user.fivetran](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/user) | resource | diff --git a/terraform/snowflake/environments/dev/.terraform.lock.hcl b/terraform/snowflake/environments/dev/.terraform.lock.hcl index 46d0c89b..038767b1 100644 --- a/terraform/snowflake/environments/dev/.terraform.lock.hcl +++ b/terraform/snowflake/environments/dev/.terraform.lock.hcl @@ -2,23 +2,23 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/snowflake-labs/snowflake" { - version = "0.70.1" - constraints = "~> 0.61, 0.70.1" + version = "0.92.0" + constraints = "~> 0.88, 0.92.0" hashes = [ - "h1:+BPGXGbe1bECu58kdWNux5DXyP1W5Z8aq79e4uEpwHI=", - "h1:CRS1028YNlK6vChFtNJZmvhlYnQW6DKqK+oplakrps0=", - "h1:xI4ate6gEYzL6bhKKKeZCRnlgztAJXHqDL8tnetwXKo=", - "zh:1d90091270608000b1bf1e853a5eff378a310841355856dba406836db4c30125", - "zh:51742df503b9e6c0f4e0fccbb56400fa23b61e60779b3d14bef2e2a6fcbd7e95", - "zh:5cb3a110d5308becd41d54bf7a223ace6b413934bd53b4f2ee652774f1ed553b", - "zh:6e8df737f7328e67387c3fe68fad150832ca498abd858275b75b50cdf1ad6490", - "zh:78af0ffce8da39c6fcbddef5ecc608df10ca88c28c68b37e830d60a8f725341d", - "zh:800c66f900575731cac55023ea33ec1c8fb77ba64eac8c0211e1bb562ae25430", - "zh:89d2db56e891399cd99faf826259b12c80b5d4b002fa689094e6d20603aab25f", - "zh:a212204451dcbbaae5d4e7c91f3083b3f3a272b5c6e58e80a4f52c7c4aa1fcdd", - "zh:c0dce1ec1c7d8338de724318b126e506fe50117697f5799fac76c414acd34047", - "zh:cf8ad38cec31fd3d24c8e285d31d876009f42128da870cd38b827709821b0158", - "zh:de27e7f5c88d071d89bd561cf6d206adba012cc7b6540b3dfc01a99554529b5f", + "h1:gEss1CYtwBknBv7k+qjk+dBz7XwGyl7YQi1MDYkYGZg=", + "h1:iZa/QVqOFfxqJwvvJQyExkS1ZW4FDiR+q7JdUkCW3iY=", + "h1:yHFALpBAbt+cJIwR42uuVECmYuWUMChSrGiPejW+ySE=", + "zh:5243cc31b0d761406009a943c713e2148543f982cb0376efc721a5b4dee16802", + "zh:7a79a12ee3022ae8105eb8efee562873bbfa9518acdf2bb572cfef40a107f962", + "zh:7f780ebc8cbaa319ccd0c93cc52cacc0966cb4fc036895ae7c7eeabc7983f275", + "zh:a30c5bb1057cc94948c1c06e361081b310a37a1625a795c3122e286b1ba4ad5d", + "zh:bc826239bffba37743b10abc36350cede21481b434221a1bc49e0cb1828a176d", + "zh:cbbcfd9e5f0fa51d90adf51e70185db3136b0fd558ae0794eccf6884cac111b2", + "zh:d285091bea835c69cc5a1e4689f0cafa95b9b68d85042a52dd49311f8753c078", + "zh:d45b2685e9fecd8b32fb43090b8b7f19541a34addf64468e646a5b6347188d5d", + "zh:d668770a1ecc7e39688816b3aaa551802958bac07c36a67ceab3791d06e2412d", + "zh:dd870eec408f2fc2c8f907ddab3192fc8bde15dc4d205c3587fee68b8636ad7a", "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + "zh:f9807dfec6d9ce60b12fe86a5dc1dfdd38a3bf85d8de8df2f5485cd9dde28263", ] } diff --git a/terraform/snowflake/environments/dev/main.tf b/terraform/snowflake/environments/dev/main.tf index b099ddf1..0bc7b546 100644 --- a/terraform/snowflake/environments/dev/main.tf +++ b/terraform/snowflake/environments/dev/main.tf @@ -20,7 +20,7 @@ terraform { required_providers { snowflake = { source = "Snowflake-Labs/snowflake" - version = "0.70.1" + version = "0.92" } } required_version = ">= 1.0" diff --git a/terraform/snowflake/environments/prd/.terraform.lock.hcl b/terraform/snowflake/environments/prd/.terraform.lock.hcl index 46d0c89b..038767b1 100644 --- a/terraform/snowflake/environments/prd/.terraform.lock.hcl +++ b/terraform/snowflake/environments/prd/.terraform.lock.hcl @@ -2,23 +2,23 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/snowflake-labs/snowflake" { - version = "0.70.1" - constraints = "~> 0.61, 0.70.1" + version = "0.92.0" + constraints = "~> 0.88, 0.92.0" hashes = [ - "h1:+BPGXGbe1bECu58kdWNux5DXyP1W5Z8aq79e4uEpwHI=", - "h1:CRS1028YNlK6vChFtNJZmvhlYnQW6DKqK+oplakrps0=", - "h1:xI4ate6gEYzL6bhKKKeZCRnlgztAJXHqDL8tnetwXKo=", - "zh:1d90091270608000b1bf1e853a5eff378a310841355856dba406836db4c30125", - "zh:51742df503b9e6c0f4e0fccbb56400fa23b61e60779b3d14bef2e2a6fcbd7e95", - "zh:5cb3a110d5308becd41d54bf7a223ace6b413934bd53b4f2ee652774f1ed553b", - "zh:6e8df737f7328e67387c3fe68fad150832ca498abd858275b75b50cdf1ad6490", - "zh:78af0ffce8da39c6fcbddef5ecc608df10ca88c28c68b37e830d60a8f725341d", - "zh:800c66f900575731cac55023ea33ec1c8fb77ba64eac8c0211e1bb562ae25430", - "zh:89d2db56e891399cd99faf826259b12c80b5d4b002fa689094e6d20603aab25f", - "zh:a212204451dcbbaae5d4e7c91f3083b3f3a272b5c6e58e80a4f52c7c4aa1fcdd", - "zh:c0dce1ec1c7d8338de724318b126e506fe50117697f5799fac76c414acd34047", - "zh:cf8ad38cec31fd3d24c8e285d31d876009f42128da870cd38b827709821b0158", - "zh:de27e7f5c88d071d89bd561cf6d206adba012cc7b6540b3dfc01a99554529b5f", + "h1:gEss1CYtwBknBv7k+qjk+dBz7XwGyl7YQi1MDYkYGZg=", + "h1:iZa/QVqOFfxqJwvvJQyExkS1ZW4FDiR+q7JdUkCW3iY=", + "h1:yHFALpBAbt+cJIwR42uuVECmYuWUMChSrGiPejW+ySE=", + "zh:5243cc31b0d761406009a943c713e2148543f982cb0376efc721a5b4dee16802", + "zh:7a79a12ee3022ae8105eb8efee562873bbfa9518acdf2bb572cfef40a107f962", + "zh:7f780ebc8cbaa319ccd0c93cc52cacc0966cb4fc036895ae7c7eeabc7983f275", + "zh:a30c5bb1057cc94948c1c06e361081b310a37a1625a795c3122e286b1ba4ad5d", + "zh:bc826239bffba37743b10abc36350cede21481b434221a1bc49e0cb1828a176d", + "zh:cbbcfd9e5f0fa51d90adf51e70185db3136b0fd558ae0794eccf6884cac111b2", + "zh:d285091bea835c69cc5a1e4689f0cafa95b9b68d85042a52dd49311f8753c078", + "zh:d45b2685e9fecd8b32fb43090b8b7f19541a34addf64468e646a5b6347188d5d", + "zh:d668770a1ecc7e39688816b3aaa551802958bac07c36a67ceab3791d06e2412d", + "zh:dd870eec408f2fc2c8f907ddab3192fc8bde15dc4d205c3587fee68b8636ad7a", "zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c", + "zh:f9807dfec6d9ce60b12fe86a5dc1dfdd38a3bf85d8de8df2f5485cd9dde28263", ] } diff --git a/terraform/snowflake/environments/prd/main.tf b/terraform/snowflake/environments/prd/main.tf index b099ddf1..0bc7b546 100644 --- a/terraform/snowflake/environments/prd/main.tf +++ b/terraform/snowflake/environments/prd/main.tf @@ -20,7 +20,7 @@ terraform { required_providers { snowflake = { source = "Snowflake-Labs/snowflake" - version = "0.70.1" + version = "0.92" } } required_version = ">= 1.0" diff --git a/terraform/snowflake/modules/database/main.tf b/terraform/snowflake/modules/database/main.tf index 22347e2c..c458b884 100644 --- a/terraform/snowflake/modules/database/main.tf +++ b/terraform/snowflake/modules/database/main.tf @@ -6,7 +6,7 @@ terraform { required_providers { snowflake = { source = "Snowflake-Labs/snowflake" - version = "~> 0.61" + version = "~> 0.88" configuration_aliases = [ snowflake.securityadmin, snowflake.sysadmin, @@ -57,7 +57,6 @@ locals { "CREATE VIEW", "MODIFY", "MONITOR", - "OWNERSHIP", "USAGE", ] } @@ -74,7 +73,6 @@ locals { READWRITECONTROL = [ "DELETE", "INSERT", - "OWNERSHIP", "TRUNCATE", "UPDATE", ] @@ -84,43 +82,8 @@ locals { view = { READ = ["SELECT", "REFERENCES"] READWRITE = ["SELECT", "REFERENCES"] - READWRITECONTROL = ["SELECT", "REFERENCES", "OWNERSHIP"] + READWRITECONTROL = ["SELECT", "REFERENCES"] } - - # Create objects for each access control - privilege combination. - # We will use them for assigning access role grants below. - database_permissions = flatten([ - for type in keys(local.database) : [ - for privilege in local.database[type] : { - type = type - privilege = privilege - } - ] - ]) - schema_permissions = flatten([ - for type in keys(local.schema) : [ - for privilege in local.schema[type] : { - type = type - privilege = privilege - } - ] - ]) - table_permissions = flatten([ - for type in keys(local.table) : [ - for privilege in local.table[type] : { - type = type - privilege = privilege - } - ] - ]) - view_permissions = flatten([ - for type in keys(local.view) : [ - for privilege in local.view[type] : { - type = type - privilege = privilege - } - ] - ]) } ####################################### @@ -153,13 +116,11 @@ resource "snowflake_role" "this" { # Role Grants # ###################################### -resource "snowflake_role_grants" "this_to_sysadmin" { - provider = snowflake.useradmin - for_each = toset(keys(local.database)) - role_name = snowflake_role.this[each.key].name - enable_multiple_grants = true - roles = ["SYSADMIN"] - depends_on = [snowflake_role.this] +resource "snowflake_grant_account_role" "this_to_sysadmin" { + provider = snowflake.useradmin + for_each = toset(keys(local.database)) + role_name = snowflake_role.this[each.key].name + parent_role_name = "SYSADMIN" } ###################################### @@ -175,59 +136,100 @@ resource "snowflake_role_grants" "this_to_sysadmin" { # https://community.snowflake.com/s/article/How-to-grant-select-on-all-future-tables-in-a-schema-and-database-level # Database grants -resource "snowflake_database_grant" "this" { - provider = snowflake.securityadmin - database_name = snowflake_database.this.name - for_each = { for p in local.database_permissions : "${p.type}-${p.privilege}" => p } - privilege = each.value.privilege - enable_multiple_grants = true - roles = ["${snowflake_database.this.name}_${each.value.type}"] - depends_on = [snowflake_role.this] +resource "snowflake_grant_privileges_to_account_role" "database" { + provider = snowflake.securityadmin + for_each = local.database + privileges = each.value + account_role_name = snowflake_role.this[each.key].name + on_account_object { + object_type = "DATABASE" + object_name = snowflake_database.this.name + } + with_grant_option = false } # Schema grants -resource "snowflake_schema_grant" "this" { - provider = snowflake.securityadmin - database_name = snowflake_database.this.name - for_each = { for p in local.schema_permissions : "${p.type}-${p.privilege}" => p } - privilege = each.value.privilege - enable_multiple_grants = true - on_future = true - roles = ["${snowflake_database.this.name}_${each.value.type}"] - depends_on = [snowflake_role.this] +resource "snowflake_grant_ownership" "schemas" { + provider = snowflake.securityadmin + account_role_name = snowflake_role.this["READWRITECONTROL"].name + on { + future { + object_type_plural = "SCHEMAS" + in_database = snowflake_database.this.name + } + } +} + +resource "snowflake_grant_privileges_to_account_role" "schemas" { + provider = snowflake.securityadmin + for_each = local.schema + privileges = each.value + account_role_name = snowflake_role.this[each.key].name + on_schema { + future_schemas_in_database = snowflake_database.this.name + } + with_grant_option = false } -resource "snowflake_schema_grant" "public" { - provider = snowflake.securityadmin - database_name = snowflake_database.this.name - schema_name = "PUBLIC" - for_each = { for p in local.schema_permissions : "${p.type}-${p.privilege}" => p } - privilege = each.value.privilege - enable_multiple_grants = true - roles = ["${snowflake_database.this.name}_${each.value.type}"] - depends_on = [snowflake_role.this] +resource "snowflake_grant_privileges_to_account_role" "public" { + provider = snowflake.securityadmin + for_each = local.schema + privileges = each.value + account_role_name = snowflake_role.this[each.key].name + on_schema { + schema_name = "${snowflake_database.this.name}.PUBLIC" + } + with_grant_option = false } # Table grants -resource "snowflake_table_grant" "this" { - provider = snowflake.securityadmin - database_name = snowflake_database.this.name - for_each = { for p in local.table_permissions : "${p.type}-${p.privilege}" => p } - privilege = each.value.privilege - enable_multiple_grants = true - on_future = true - roles = ["${snowflake_database.this.name}_${each.value.type}"] - depends_on = [snowflake_role.this] +resource "snowflake_grant_ownership" "tables" { + provider = snowflake.securityadmin + account_role_name = snowflake_role.this["READWRITECONTROL"].name + on { + future { + object_type_plural = "TABLES" + in_database = snowflake_database.this.name + } + } +} + +resource "snowflake_grant_privileges_to_account_role" "tables" { + provider = snowflake.securityadmin + for_each = local.table + privileges = each.value + account_role_name = snowflake_role.this[each.key].name + on_schema_object { + future { + object_type_plural = "TABLES" + in_database = snowflake_database.this.name + } + } + with_grant_option = false } # View grants -resource "snowflake_view_grant" "this" { - provider = snowflake.securityadmin - database_name = snowflake_database.this.name - for_each = { for p in local.view_permissions : "${p.type}-${p.privilege}" => p } - privilege = each.value.privilege - enable_multiple_grants = true - on_future = true - roles = ["${snowflake_database.this.name}_${each.value.type}"] - depends_on = [snowflake_role.this] +resource "snowflake_grant_ownership" "views" { + provider = snowflake.securityadmin + account_role_name = snowflake_role.this["READWRITECONTROL"].name + on { + future { + object_type_plural = "VIEWS" + in_database = snowflake_database.this.name + } + } +} + +resource "snowflake_grant_privileges_to_account_role" "views" { + provider = snowflake.securityadmin + for_each = local.view + privileges = each.value + account_role_name = snowflake_role.this[each.key].name + on_schema_object { + future { + object_type_plural = "VIEWS" + in_database = snowflake_database.this.name + } + } + with_grant_option = false } diff --git a/terraform/snowflake/modules/elt/main.tf b/terraform/snowflake/modules/elt/main.tf index 54d23d95..cf6315a0 100644 --- a/terraform/snowflake/modules/elt/main.tf +++ b/terraform/snowflake/modules/elt/main.tf @@ -6,7 +6,7 @@ terraform { required_providers { snowflake = { source = "Snowflake-Labs/snowflake" - version = "~> 0.61" + version = "~> 0.88" configuration_aliases = [ snowflake.accountadmin, snowflake.securityadmin, diff --git a/terraform/snowflake/modules/elt/roles.tf b/terraform/snowflake/modules/elt/roles.tf index 47e0a12c..a84e3929 100644 --- a/terraform/snowflake/modules/elt/roles.tf +++ b/terraform/snowflake/modules/elt/roles.tf @@ -52,149 +52,131 @@ resource "snowflake_role" "logger" { # https:#docs.snowflake.com/en/user-guide/security-access-control-considerations#aligning-object-access-with-business-functions # This allows SYSADMIN to make additional grants of database objects to these roles. -resource "snowflake_role_grants" "loader_to_sysadmin" { - provider = snowflake.useradmin - role_name = snowflake_role.loader.name - enable_multiple_grants = true - roles = ["SYSADMIN"] +resource "snowflake_grant_account_role" "loader_to_sysadmin" { + provider = snowflake.useradmin + role_name = snowflake_role.loader.name + parent_role_name = "SYSADMIN" } -resource "snowflake_role_grants" "transformer_to_sysadmin" { - provider = snowflake.useradmin - role_name = snowflake_role.transformer.name - enable_multiple_grants = true - roles = ["SYSADMIN"] +resource "snowflake_grant_account_role" "transformer_to_sysadmin" { + provider = snowflake.useradmin + role_name = snowflake_role.transformer.name + parent_role_name = "SYSADMIN" } -resource "snowflake_role_grants" "reporter_to_sysadmin" { - provider = snowflake.useradmin - role_name = snowflake_role.reporter.name - enable_multiple_grants = true - roles = ["SYSADMIN"] +resource "snowflake_grant_account_role" "reporter_to_sysadmin" { + provider = snowflake.useradmin + role_name = snowflake_role.reporter.name + parent_role_name = "SYSADMIN" } -resource "snowflake_role_grants" "reader_to_sysadmin" { - provider = snowflake.useradmin - role_name = snowflake_role.reader.name - enable_multiple_grants = true - roles = ["SYSADMIN"] +resource "snowflake_grant_account_role" "reader_to_sysadmin" { + provider = snowflake.useradmin + role_name = snowflake_role.reader.name + parent_role_name = "SYSADMIN" } # NOTE: logger has elevated privileges, so it is assigned # directly to accountadmin -resource "snowflake_role_grants" "logger_to_accountadmin" { - provider = snowflake.accountadmin - role_name = snowflake_role.logger.name - enable_multiple_grants = true - roles = ["SYSADMIN"] +resource "snowflake_grant_account_role" "logger_to_accountadmin" { + provider = snowflake.accountadmin + role_name = snowflake_role.logger.name + parent_role_name = "ACCOUNTADMIN" } # Loader has RWC privileges in RAW -resource "snowflake_role_grants" "raw_rwc_to_loader" { - provider = snowflake.useradmin - role_name = "${module.raw.name}_READWRITECONTROL" - enable_multiple_grants = true - roles = [snowflake_role.loader.name] +resource "snowflake_grant_account_role" "raw_rwc_to_loader" { + provider = snowflake.useradmin + role_name = "${module.raw.name}_READWRITECONTROL" + parent_role_name = snowflake_role.loader.name } # Reporter has read privileges in ANALYTICS -resource "snowflake_role_grants" "analytics_r_to_reporter" { - provider = snowflake.useradmin - role_name = "${module.analytics.name}_READ" - enable_multiple_grants = true - roles = [snowflake_role.reporter.name] +resource "snowflake_grant_account_role" "analytics_r_to_reporter" { + provider = snowflake.useradmin + role_name = "${module.analytics.name}_READ" + parent_role_name = snowflake_role.reporter.name } # Transformer has RWC privileges in TRANSFORM -resource "snowflake_role_grants" "transform_rwc_to_transformer" { - provider = snowflake.useradmin - role_name = "${module.transform.name}_READWRITECONTROL" - enable_multiple_grants = true - roles = [snowflake_role.transformer.name] +resource "snowflake_grant_account_role" "transform_rwc_to_transformer" { + provider = snowflake.useradmin + role_name = "${module.transform.name}_READWRITECONTROL" + parent_role_name = snowflake_role.transformer.name } # Transformer has RWC privileges in ANALYTICS -resource "snowflake_role_grants" "analytics_rwc_to_transformer" { - provider = snowflake.useradmin - role_name = "${module.analytics.name}_READWRITECONTROL" - enable_multiple_grants = true - roles = [snowflake_role.transformer.name] +resource "snowflake_grant_account_role" "analytics_rwc_to_transformer" { + provider = snowflake.useradmin + role_name = "${module.analytics.name}_READWRITECONTROL" + parent_role_name = snowflake_role.transformer.name } # Transformer has read permissions in RAW -resource "snowflake_role_grants" "raw_r_to_transformer" { - provider = snowflake.useradmin - role_name = "${module.raw.name}_READ" - enable_multiple_grants = true - roles = [snowflake_role.transformer.name] +resource "snowflake_grant_account_role" "raw_r_to_transformer" { + provider = snowflake.useradmin + role_name = "${module.raw.name}_READ" + parent_role_name = snowflake_role.transformer.name } # Transformer can use the TRANSFORMING warehouse -resource "snowflake_role_grants" "transforming_to_transformer" { - provider = snowflake.useradmin - for_each = toset(values(module.transforming)[*].access_role_name) - role_name = each.key - enable_multiple_grants = true - roles = [snowflake_role.transformer.name] +resource "snowflake_grant_account_role" "transforming_to_transformer" { + provider = snowflake.useradmin + for_each = toset(values(module.transforming)[*].access_role_name) + role_name = each.key + parent_role_name = snowflake_role.transformer.name } # Reporter can use the REPORTING warehouse -resource "snowflake_role_grants" "reporting_to_reporter" { - provider = snowflake.useradmin - for_each = toset(values(module.reporting)[*].access_role_name) - role_name = each.key - enable_multiple_grants = true - roles = [snowflake_role.reporter.name] +resource "snowflake_grant_account_role" "reporting_to_reporter" { + provider = snowflake.useradmin + for_each = toset(values(module.reporting)[*].access_role_name) + role_name = each.key + parent_role_name = snowflake_role.reporter.name } # Loader can use the LOADING warehouse -resource "snowflake_role_grants" "loading_to_loader" { - provider = snowflake.useradmin - for_each = toset(values(module.loading)[*].access_role_name) - role_name = each.key - enable_multiple_grants = true - roles = [snowflake_role.loader.name] +resource "snowflake_grant_account_role" "loading_to_loader" { + provider = snowflake.useradmin + for_each = toset(values(module.loading)[*].access_role_name) + role_name = each.key + parent_role_name = snowflake_role.loader.name } # Reader has read permissions in RAW -resource "snowflake_role_grants" "raw_r_to_reader" { - provider = snowflake.useradmin - role_name = "${module.raw.name}_READ" - enable_multiple_grants = true - roles = [snowflake_role.reader.name] +resource "snowflake_grant_account_role" "raw_r_to_reader" { + provider = snowflake.useradmin + role_name = "${module.raw.name}_READ" + parent_role_name = snowflake_role.reader.name } # Reader has read permissions in TRANSFORM -resource "snowflake_role_grants" "transform_r_to_reader" { - provider = snowflake.useradmin - role_name = "${module.transform.name}_READ" - enable_multiple_grants = true - roles = [snowflake_role.reader.name] +resource "snowflake_grant_account_role" "transform_r_to_reader" { + provider = snowflake.useradmin + role_name = "${module.transform.name}_READ" + parent_role_name = snowflake_role.reader.name } # Reader has read permissions in ANALYTICS -resource "snowflake_role_grants" "analytics_r_to_reader" { - provider = snowflake.useradmin - role_name = "${module.analytics.name}_READ" - enable_multiple_grants = true - roles = [snowflake_role.reader.name] +resource "snowflake_grant_account_role" "analytics_r_to_reader" { + provider = snowflake.useradmin + role_name = "${module.analytics.name}_READ" + parent_role_name = snowflake_role.reader.name } # Reader can use the REPORTING warehouse -resource "snowflake_role_grants" "reporting_to_reader" { - provider = snowflake.useradmin - for_each = toset(values(module.reporting)[*].access_role_name) - role_name = each.key - enable_multiple_grants = true - roles = [snowflake_role.reader.name] +resource "snowflake_grant_account_role" "reporting_to_reader" { + provider = snowflake.useradmin + for_each = toset(values(module.reporting)[*].access_role_name) + role_name = each.key + parent_role_name = snowflake_role.reader.name } # Logger can use the LOGGING warehouse -resource "snowflake_role_grants" "logging_to_logger" { - provider = snowflake.useradmin - role_name = module.logging.access_role_name - enable_multiple_grants = true - roles = [snowflake_role.logger.name] +resource "snowflake_grant_account_role" "logging_to_logger" { + provider = snowflake.useradmin + role_name = module.logging.access_role_name + parent_role_name = snowflake_role.logger.name } ###################################### @@ -202,16 +184,12 @@ resource "snowflake_role_grants" "logging_to_logger" { ###################################### # Imported privileges for logging -resource "snowflake_database_grant" "this" { - provider = snowflake.accountadmin - database_name = "SNOWFLAKE" - privilege = "IMPORTED PRIVILEGES" - enable_multiple_grants = true - roles = [snowflake_role.logger.name] - # Sigh... we need to ignore changes because the terraform provider doesn't - # properly track this resource: - # https://github.com/Snowflake-Labs/terraform-provider-snowflake/issues/1998 - lifecycle { - ignore_changes = all +resource "snowflake_grant_privileges_to_account_role" "imported_privileges_to_logger" { + provider = snowflake.accountadmin + account_role_name = snowflake_role.logger.name + privileges = ["IMPORTED PRIVILEGES"] + on_account_object { + object_type = "DATABASE" + object_name = "SNOWFLAKE" } } diff --git a/terraform/snowflake/modules/elt/users.tf b/terraform/snowflake/modules/elt/users.tf index 6ae11d21..2976a0f3 100644 --- a/terraform/snowflake/modules/elt/users.tf +++ b/terraform/snowflake/modules/elt/users.tf @@ -62,37 +62,32 @@ resource "snowflake_user" "sentinel" { # Role Grants # ###################################### -resource "snowflake_role_grants" "transformer_to_dbt" { - provider = snowflake.useradmin - role_name = snowflake_role.transformer.name - enable_multiple_grants = true - users = [snowflake_user.dbt.name] +resource "snowflake_grant_account_role" "transformer_to_dbt" { + provider = snowflake.useradmin + role_name = snowflake_role.transformer.name + user_name = snowflake_user.dbt.name } -resource "snowflake_role_grants" "loader_to_airflow" { - provider = snowflake.useradmin - role_name = snowflake_role.loader.name - enable_multiple_grants = true - users = [snowflake_user.airflow.name] +resource "snowflake_grant_account_role" "loader_to_airflow" { + provider = snowflake.useradmin + role_name = snowflake_role.loader.name + user_name = snowflake_user.airflow.name } -resource "snowflake_role_grants" "loader_to_fivetran" { - provider = snowflake.useradmin - role_name = snowflake_role.loader.name - enable_multiple_grants = true - users = [snowflake_user.fivetran.name] +resource "snowflake_grant_account_role" "loader_to_fivetran" { + provider = snowflake.useradmin + role_name = snowflake_role.loader.name + user_name = snowflake_user.fivetran.name } -resource "snowflake_role_grants" "reader_to_github_ci" { - provider = snowflake.useradmin - role_name = snowflake_role.reader.name - enable_multiple_grants = true - users = [snowflake_user.github_ci.name] +resource "snowflake_grant_account_role" "reader_to_github_ci" { + provider = snowflake.useradmin + role_name = snowflake_role.reader.name + user_name = snowflake_user.github_ci.name } -resource "snowflake_role_grants" "logger_to_sentinel" { - provider = snowflake.useradmin - role_name = snowflake_role.logger.name - enable_multiple_grants = true - users = [snowflake_user.sentinel.name] +resource "snowflake_grant_account_role" "logger_to_sentinel" { + provider = snowflake.useradmin + role_name = snowflake_role.logger.name + user_name = snowflake_user.sentinel.name } diff --git a/terraform/snowflake/modules/warehouse/main.tf b/terraform/snowflake/modules/warehouse/main.tf index 62a06221..c8b2e909 100644 --- a/terraform/snowflake/modules/warehouse/main.tf +++ b/terraform/snowflake/modules/warehouse/main.tf @@ -6,7 +6,7 @@ terraform { required_providers { snowflake = { source = "Snowflake-Labs/snowflake" - version = "~> 0.61" + version = "~> 0.88" configuration_aliases = [ snowflake.securityadmin, snowflake.sysadmin, @@ -60,22 +60,23 @@ resource "snowflake_role" "this" { # Role Grants # ################################# -resource "snowflake_role_grants" "this_to_sysadmin" { - provider = snowflake.useradmin - role_name = snowflake_role.this.name - enable_multiple_grants = true - roles = ["SYSADMIN"] +resource "snowflake_grant_account_role" "this_to_sysadmin" { + provider = snowflake.useradmin + role_name = snowflake_role.this.name + parent_role_name = "SYSADMIN" } ################################# # Warehouse Grants # ################################# -resource "snowflake_warehouse_grant" "this" { +resource "snowflake_grant_privileges_to_account_role" "this" { provider = snowflake.securityadmin - for_each = toset(local.warehouse.MOU) - warehouse_name = snowflake_warehouse.this.name - privilege = each.key - roles = [snowflake_role.this.name] + privileges = local.warehouse.MOU + account_role_name = snowflake_role.this.name + on_account_object { + object_type = "WAREHOUSE" + object_name = snowflake_warehouse.this.name + } with_grant_option = false }