diff --git a/README.md b/README.md index e25adb7..9372c6e 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ module "snowflake_role" { | [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | | [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.
Map of maps. Keys are names of descriptors. Values are maps of the form
`{
format = string
labels = list(string)
}`
(Type is `any` so the map values can later be enhanced to provide additional options.)
`format` is a Terraform format string to be passed to the `format()` function.
`labels` is a list of labels, in order, to pass to `format()` function.
Label values will be normalized before being passed to `format()` so they will be
identical to how they appear in `id`.
Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no | | [descriptor\_name](#input\_descriptor\_name) | Name of the descriptor used to form a resource name | `string` | `"snowflake-role"` | no | +| [dynamic\_table\_grants](#input\_dynamic\_table\_grants) | Grants on a dynamic\_table level |
list(object({
database_name = string
schema_name = optional(string)
dynamic_table_name = optional(string)
on_future = optional(bool, false)
on_all = optional(bool, false)
all_privileges = optional(bool)
privileges = optional(list(string), null)
}))
| `[]` | no | | [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no | | [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | | [external\_table\_grants](#input\_external\_table\_grants) | Grants on a external table level |
list(object({
database_name = string
schema_name = string
external_table_name = optional(string)
on_future = optional(bool)
on_all = optional(bool)
privileges = list(string)
}))
| `[]` | no | @@ -130,6 +131,7 @@ module "snowflake_role" { | [snowflake_account_grant.this](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/account_grant) | resource | | [snowflake_database_grant.this](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/database_grant) | resource | | [snowflake_external_table_grant.this](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/external_table_grant) | resource | +| [snowflake_grant_privileges_to_role.dynamic_table](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/grant_privileges_to_role) | resource | | [snowflake_role.this](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role) | resource | | [snowflake_role_grants.granted_roles](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | | [snowflake_role_grants.granted_to](https://registry.terraform.io/providers/Snowflake-Labs/snowflake/latest/docs/resources/role_grants) | resource | diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 2bd274a..60acc53 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -38,4 +38,25 @@ module "snowflake_role" { privileges = ["SELECT"] } ] + + dynamic_table_grants = [ + { + database_name = "LOGS_DB" + on_all = true + on_future = true + all_privileges = true + }, + { + database_name = "TEST_DB" + schema_name = "BRONZE" + on_all = true + all_privileges = true + }, + { + database_name = "TEST_DB" + schema_name = "SILVER" + dynamic_table_name = "EXAMPLE" + privileges = ["SELECT"] + }, + ] } diff --git a/locals.tf b/locals.tf index 2cd6ee9..3ce6838 100644 --- a/locals.tf +++ b/locals.tf @@ -58,4 +58,17 @@ locals { privilege = privilege } }]...) + + dynamic_table_grants = merge([for grant in var.dynamic_table_grants : { + for key, value in { "dynamic_table_name" = grant.dynamic_table_name, "on_all" = grant.on_all, "on_future" = grant.on_future } : + "${grant.database_name}/${coalesce(grant.schema_name, "all")}/${key == "dynamic_table_name" ? value : key}" => { + database_name = grant.database_name + schema_name = grant.schema_name + dynamic_table_name = key == "dynamic_table_name" ? value : null + on_future = key == "on_future" ? value : false + on_all = key == "on_all" ? value : false + privileges = grant.privileges + all_privileges = grant.all_privileges + } if(key == "dynamic_table_name" && value != null) || value == true + }]...) } diff --git a/main.tf b/main.tf index 53c4f70..796b65c 100644 --- a/main.tf +++ b/main.tf @@ -100,3 +100,35 @@ resource "snowflake_account_grant" "this" { with_grant_option = false } + +resource "snowflake_grant_privileges_to_role" "dynamic_table" { + for_each = module.this.enabled ? local.dynamic_table_grants : {} + + privileges = each.value.privileges + all_privileges = each.value.all_privileges + role_name = one(snowflake_role.this[*].name) + + on_schema_object { + + object_type = each.value.dynamic_table_name != null ? "DYNAMIC TABLE" : null + object_name = each.value.dynamic_table_name != null ? join(".", [each.value.database_name, each.value.schema_name, each.value.dynamic_table_name]) : null + + dynamic "future" { + for_each = each.value.on_future ? [1] : [] + content { + object_type_plural = "DYNAMIC TABLES" + in_database = each.value.schema_name != null ? null : each.value.database_name + in_schema = each.value.schema_name != null ? join(".", [each.value.database_name, each.value.schema_name]) : null + } + } + + dynamic "all" { + for_each = each.value.on_all ? [1] : [] + content { + object_type_plural = "DYNAMIC TABLES" + in_database = each.value.schema_name != null ? null : each.value.database_name + in_schema = each.value.schema_name != null ? join(".", [each.value.database_name, each.value.schema_name]) : null + } + } + } +} diff --git a/variables.tf b/variables.tf index c25428f..4e4550f 100644 --- a/variables.tf +++ b/variables.tf @@ -110,6 +110,28 @@ variable "view_grants" { } } +variable "dynamic_table_grants" { + description = "Grants on a dynamic_table level" + type = list(object({ + database_name = string + schema_name = optional(string) + dynamic_table_name = optional(string) + on_future = optional(bool, false) + on_all = optional(bool, false) + all_privileges = optional(bool) + privileges = optional(list(string), null) + })) + default = [] + validation { + condition = alltrue([for grant in var.dynamic_table_grants : !anytrue([grant.privileges == null && grant.all_privileges == null, grant.privileges != null && grant.all_privileges != null])]) + error_message = "Variable `dynamic_table_grants` fails validation - only one of `privileges` or `all_privileges` can be set." + } + validation { + condition = alltrue([for grant in var.dynamic_table_grants : !alltrue([grant.dynamic_table_name != null, grant.on_future || grant.on_all])]) + error_message = "Variable `dynamic_table_grants` fails validation - when `dynamic_table_name` is set, `on_future` and `on_all` have to be false / not set." + } +} + variable "descriptor_name" { description = "Name of the descriptor used to form a resource name" type = string