From 2de5b7ca793b6f6707ea7be4453332355aa5b78b Mon Sep 17 00:00:00 2001 From: David Rosin Date: Tue, 11 Feb 2025 15:02:02 +0100 Subject: [PATCH 1/5] feat: support aws_dynamodb_resource_policy (closes #95) --- README.md | 2 + examples/resource-based-policy/README.md | 57 ++++++++++++++ examples/resource-based-policy/main.tf | 83 +++++++++++++++++++++ examples/resource-based-policy/outputs.tf | 19 +++++ examples/resource-based-policy/variables.tf | 0 examples/resource-based-policy/versions.tf | 14 ++++ main.tf | 7 ++ variables.tf | 6 ++ wrappers/main.tf | 1 + 9 files changed, 189 insertions(+) create mode 100644 examples/resource-based-policy/README.md create mode 100644 examples/resource-based-policy/main.tf create mode 100644 examples/resource-based-policy/outputs.tf create mode 100644 examples/resource-based-policy/variables.tf create mode 100644 examples/resource-based-policy/versions.tf diff --git a/README.md b/README.md index 3be8499..1b6d936 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ No modules. | [aws_appautoscaling_target.index_write](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_target) | resource | | [aws_appautoscaling_target.table_read](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_target) | resource | | [aws_appautoscaling_target.table_write](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_target) | resource | +| [aws_dynamodb_resource_policy.table_resource_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_resource_policy) | resource | | [aws_dynamodb_table.autoscaled](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | resource | | [aws_dynamodb_table.autoscaled_gsi_ignore](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | resource | | [aws_dynamodb_table.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | resource | @@ -120,6 +121,7 @@ No modules. | [range\_key](#input\_range\_key) | The attribute to use as the range (sort) key. Must also be defined as an attribute | `string` | `null` | no | | [read\_capacity](#input\_read\_capacity) | The number of read units for this table. If the billing\_mode is PROVISIONED, this field should be greater than 0 | `number` | `null` | no | | [replica\_regions](#input\_replica\_regions) | Region names for creating replicas for a global DynamoDB table. | `any` | `[]` | no | +| [resource\_based\_policy\_json](#input\_resource\_based\_policy\_json) | The JSON definition of the resource-based policy. | `string` | `null` | no | | [restore\_date\_time](#input\_restore\_date\_time) | Time of the point-in-time recovery point to restore. | `string` | `null` | no | | [restore\_source\_name](#input\_restore\_source\_name) | Name of the table to restore. Must match the name of an existing table. | `string` | `null` | no | | [restore\_source\_table\_arn](#input\_restore\_source\_table\_arn) | ARN of the source table to restore. Must be supplied for cross-region restores. | `string` | `null` | no | diff --git a/examples/resource-based-policy/README.md b/examples/resource-based-policy/README.md new file mode 100644 index 0000000..9692751 --- /dev/null +++ b/examples/resource-based-policy/README.md @@ -0,0 +1,57 @@ +# DynamoDB Table with resource-based policy example + +Configuration in this directory creates AWS DynamoDB table with a resource-based policy. + +## Usage + +To run this example you need to execute: + +```bash +terraform init +terraform plan +terraform apply +``` + +Note that this example may create resources which can cost money (AWS Elastic IP, for example). Run `terraform destroy` when you don't need these resources. + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | >= 5.72.1 | +| [random](#requirement\_random) | >= 2.0 | + +## Providers + +| Name | Version | +|------|---------| +| [random](#provider\_random) | >= 2.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [disabled\_dynamodb\_table](#module\_disabled\_dynamodb\_table) | ../../ | n/a | +| [dynamodb\_table](#module\_dynamodb\_table) | ../../ | n/a | + +## Resources + +| Name | Type | +|------|------| +| [random_pet.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource | + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [dynamodb\_table\_arn](#output\_dynamodb\_table\_arn) | ARN of the DynamoDB table | +| [dynamodb\_table\_id](#output\_dynamodb\_table\_id) | ID of the DynamoDB table | +| [dynamodb\_table\_stream\_arn](#output\_dynamodb\_table\_stream\_arn) | The ARN of the Table Stream. Only available when var.stream\_enabled is true | +| [dynamodb\_table\_stream\_label](#output\_dynamodb\_table\_stream\_label) | A timestamp, in ISO 8601 format of the Table Stream. Only available when var.stream\_enabled is true | + diff --git a/examples/resource-based-policy/main.tf b/examples/resource-based-policy/main.tf new file mode 100644 index 0000000..ed03c40 --- /dev/null +++ b/examples/resource-based-policy/main.tf @@ -0,0 +1,83 @@ +provider "aws" { + region = "eu-west-1" +} + +resource "random_pet" "this" { + length = 2 +} + +module "dynamodb_table" { + source = "../../" + + name = "my-table-${random_pet.this.id}" + hash_key = "id" + range_key = "title" + table_class = "STANDARD" + deletion_protection_enabled = false + + attributes = [ + { + name = "id" + type = "N" + }, + { + name = "title" + type = "S" + }, + { + name = "age" + type = "N" + } + ] + + global_secondary_indexes = [ + { + name = "TitleIndex" + hash_key = "title" + range_key = "age" + projection_type = "INCLUDE" + non_key_attributes = ["id"] + + on_demand_throughput = { + max_write_request_units = 1 + max_read_request_units = 1 + } + } + ] + + on_demand_throughput = { + max_read_request_units = 1 + max_write_request_units = 1 + } + + resource_based_policy_json = < Date: Wed, 12 Feb 2025 11:49:24 +0100 Subject: [PATCH 2/5] Rename policy resource Co-authored-by: Anton Babenko --- main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.tf b/main.tf index e22495e..c6b8412 100644 --- a/main.tf +++ b/main.tf @@ -377,7 +377,7 @@ resource "aws_dynamodb_table" "autoscaled_gsi_ignore" { } } -resource "aws_dynamodb_resource_policy" "table_resource_policy" { +resource "aws_dynamodb_resource_policy" "this" { count = var.create_table && var.resource_based_policy_json != null ? 1 : 0 resource_arn = try(aws_dynamodb_table.this[0].arn, aws_dynamodb_table.autoscaled[0].arn, aws_dynamodb_table.autoscaled_gsi_ignore[0].arn, "") From cb1e89a33a504446fd7d8f734d67f50a6141474f Mon Sep 17 00:00:00 2001 From: David Rosin Date: Wed, 12 Feb 2025 11:50:33 +0100 Subject: [PATCH 3/5] rename policy variable Co-authored-by: Anton Babenko --- variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/variables.tf b/variables.tf index 69f6d9b..2261d86 100644 --- a/variables.tf +++ b/variables.tf @@ -210,7 +210,7 @@ variable "restore_to_latest_time" { default = null } -variable "resource_based_policy_json" { +variable "resource_policy" { description = "The JSON definition of the resource-based policy." type = string default = null From ad9975c88f5a966775d65f3fece12b9f459a430a Mon Sep 17 00:00:00 2001 From: David Rosin Date: Wed, 12 Feb 2025 12:16:43 +0100 Subject: [PATCH 4/5] Apply suggested changes --- README.md | 4 +- examples/basic/main.tf | 17 +++++ examples/resource-based-policy/README.md | 57 -------------- examples/resource-based-policy/main.tf | 83 --------------------- examples/resource-based-policy/outputs.tf | 19 ----- examples/resource-based-policy/variables.tf | 0 examples/resource-based-policy/versions.tf | 14 ---- main.tf | 4 +- wrappers/main.tf | 2 +- 9 files changed, 22 insertions(+), 178 deletions(-) delete mode 100644 examples/resource-based-policy/README.md delete mode 100644 examples/resource-based-policy/main.tf delete mode 100644 examples/resource-based-policy/outputs.tf delete mode 100644 examples/resource-based-policy/variables.tf delete mode 100644 examples/resource-based-policy/versions.tf diff --git a/README.md b/README.md index 1b6d936..a797fd3 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ No modules. | [aws_appautoscaling_target.index_write](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_target) | resource | | [aws_appautoscaling_target.table_read](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_target) | resource | | [aws_appautoscaling_target.table_write](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_target) | resource | -| [aws_dynamodb_resource_policy.table_resource_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_resource_policy) | resource | +| [aws_dynamodb_resource_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_resource_policy) | resource | | [aws_dynamodb_table.autoscaled](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | resource | | [aws_dynamodb_table.autoscaled_gsi_ignore](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | resource | | [aws_dynamodb_table.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/dynamodb_table) | resource | @@ -121,7 +121,7 @@ No modules. | [range\_key](#input\_range\_key) | The attribute to use as the range (sort) key. Must also be defined as an attribute | `string` | `null` | no | | [read\_capacity](#input\_read\_capacity) | The number of read units for this table. If the billing\_mode is PROVISIONED, this field should be greater than 0 | `number` | `null` | no | | [replica\_regions](#input\_replica\_regions) | Region names for creating replicas for a global DynamoDB table. | `any` | `[]` | no | -| [resource\_based\_policy\_json](#input\_resource\_based\_policy\_json) | The JSON definition of the resource-based policy. | `string` | `null` | no | +| [resource\_policy](#input\_resource\_policy) | The JSON definition of the resource-based policy. | `string` | `null` | no | | [restore\_date\_time](#input\_restore\_date\_time) | Time of the point-in-time recovery point to restore. | `string` | `null` | no | | [restore\_source\_name](#input\_restore\_source\_name) | Name of the table to restore. Must match the name of an existing table. | `string` | `null` | no | | [restore\_source\_table\_arn](#input\_restore\_source\_table\_arn) | ARN of the source table to restore. Must be supplied for cross-region restores. | `string` | `null` | no | diff --git a/examples/basic/main.tf b/examples/basic/main.tf index 28133e9..3ce4f01 100644 --- a/examples/basic/main.tf +++ b/examples/basic/main.tf @@ -50,6 +50,23 @@ module "dynamodb_table" { max_write_request_units = 1 } + resource_policy = < -## Requirements - -| Name | Version | -|------|---------| -| [terraform](#requirement\_terraform) | >= 1.0 | -| [aws](#requirement\_aws) | >= 5.72.1 | -| [random](#requirement\_random) | >= 2.0 | - -## Providers - -| Name | Version | -|------|---------| -| [random](#provider\_random) | >= 2.0 | - -## Modules - -| Name | Source | Version | -|------|--------|---------| -| [disabled\_dynamodb\_table](#module\_disabled\_dynamodb\_table) | ../../ | n/a | -| [dynamodb\_table](#module\_dynamodb\_table) | ../../ | n/a | - -## Resources - -| Name | Type | -|------|------| -| [random_pet.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource | - -## Inputs - -No inputs. - -## Outputs - -| Name | Description | -|------|-------------| -| [dynamodb\_table\_arn](#output\_dynamodb\_table\_arn) | ARN of the DynamoDB table | -| [dynamodb\_table\_id](#output\_dynamodb\_table\_id) | ID of the DynamoDB table | -| [dynamodb\_table\_stream\_arn](#output\_dynamodb\_table\_stream\_arn) | The ARN of the Table Stream. Only available when var.stream\_enabled is true | -| [dynamodb\_table\_stream\_label](#output\_dynamodb\_table\_stream\_label) | A timestamp, in ISO 8601 format of the Table Stream. Only available when var.stream\_enabled is true | - diff --git a/examples/resource-based-policy/main.tf b/examples/resource-based-policy/main.tf deleted file mode 100644 index ed03c40..0000000 --- a/examples/resource-based-policy/main.tf +++ /dev/null @@ -1,83 +0,0 @@ -provider "aws" { - region = "eu-west-1" -} - -resource "random_pet" "this" { - length = 2 -} - -module "dynamodb_table" { - source = "../../" - - name = "my-table-${random_pet.this.id}" - hash_key = "id" - range_key = "title" - table_class = "STANDARD" - deletion_protection_enabled = false - - attributes = [ - { - name = "id" - type = "N" - }, - { - name = "title" - type = "S" - }, - { - name = "age" - type = "N" - } - ] - - global_secondary_indexes = [ - { - name = "TitleIndex" - hash_key = "title" - range_key = "age" - projection_type = "INCLUDE" - non_key_attributes = ["id"] - - on_demand_throughput = { - max_write_request_units = 1 - max_read_request_units = 1 - } - } - ] - - on_demand_throughput = { - max_read_request_units = 1 - max_write_request_units = 1 - } - - resource_based_policy_json = < Date: Thu, 13 Feb 2025 11:32:14 +0100 Subject: [PATCH 5/5] Move table arn to separate locals --- main.tf | 8 ++++++-- outputs.tf | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/main.tf b/main.tf index 632f112..e0d9167 100644 --- a/main.tf +++ b/main.tf @@ -1,3 +1,7 @@ +locals { + dynamodb_table_arn = try(aws_dynamodb_table.this[0].arn, aws_dynamodb_table.autoscaled[0].arn, aws_dynamodb_table.autoscaled_gsi_ignore[0].arn, "") +} + resource "aws_dynamodb_table" "this" { count = var.create_table && !var.autoscaling_enabled ? 1 : 0 @@ -380,6 +384,6 @@ resource "aws_dynamodb_table" "autoscaled_gsi_ignore" { resource "aws_dynamodb_resource_policy" "this" { count = var.create_table && var.resource_policy != null ? 1 : 0 - resource_arn = try(aws_dynamodb_table.this[0].arn, aws_dynamodb_table.autoscaled[0].arn, aws_dynamodb_table.autoscaled_gsi_ignore[0].arn, "") - policy = replace(var.resource_policy, "__DYNAMODB_TABLE_ARN__", try(aws_dynamodb_table.this[0].arn, aws_dynamodb_table.autoscaled[0].arn, aws_dynamodb_table.autoscaled_gsi_ignore[0].arn, "")) + resource_arn = local.dynamodb_table_arn + policy = replace(var.resource_policy, "__DYNAMODB_TABLE_ARN__", local.dynamodb_table_arn) } diff --git a/outputs.tf b/outputs.tf index fa07482..0d68576 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,6 +1,6 @@ output "dynamodb_table_arn" { description = "ARN of the DynamoDB table" - value = try(aws_dynamodb_table.this[0].arn, aws_dynamodb_table.autoscaled[0].arn, aws_dynamodb_table.autoscaled_gsi_ignore[0].arn, "") + value = local.dynamodb_table_arn } output "dynamodb_table_id" {