Skip to content

Commit

Permalink
Merge pull request #11 from getindata/feature/dynamic_table_support
Browse files Browse the repository at this point in the history
feat: Add support for dynamic table grants
  • Loading branch information
dgniewek authored Jan 5, 2024
2 parents 03071d2 + fff30a5 commit f500754
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ module "snowflake_role" {
| <a name="input_delimiter"></a> [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.<br>Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no |
| <a name="input_descriptor_formats"></a> [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.<br>Map of maps. Keys are names of descriptors. Values are maps of the form<br>`{<br> format = string<br> labels = list(string)<br>}`<br>(Type is `any` so the map values can later be enhanced to provide additional options.)<br>`format` is a Terraform format string to be passed to the `format()` function.<br>`labels` is a list of labels, in order, to pass to `format()` function.<br>Label values will be normalized before being passed to `format()` so they will be<br>identical to how they appear in `id`.<br>Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no |
| <a name="input_descriptor_name"></a> [descriptor\_name](#input\_descriptor\_name) | Name of the descriptor used to form a resource name | `string` | `"snowflake-role"` | no |
| <a name="input_dynamic_table_grants"></a> [dynamic\_table\_grants](#input\_dynamic\_table\_grants) | Grants on a dynamic\_table level | <pre>list(object({<br> database_name = string<br> schema_name = optional(string)<br> dynamic_table_name = optional(string)<br> on_future = optional(bool, false)<br> on_all = optional(bool, false)<br> all_privileges = optional(bool)<br> privileges = optional(list(string), null)<br> }))</pre> | `[]` | no |
| <a name="input_enabled"></a> [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no |
| <a name="input_environment"></a> [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no |
| <a name="input_external_table_grants"></a> [external\_table\_grants](#input\_external\_table\_grants) | Grants on a external table level | <pre>list(object({<br> database_name = string<br> schema_name = string<br> external_table_name = optional(string)<br> on_future = optional(bool)<br> on_all = optional(bool)<br> privileges = list(string)<br> }))</pre> | `[]` | no |
Expand Down Expand Up @@ -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 |
Expand Down
21 changes: 21 additions & 0 deletions examples/complete/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
},
]
}
13 changes: 13 additions & 0 deletions locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
}]...)
}
32 changes: 32 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}
}
22 changes: 22 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit f500754

Please sign in to comment.