diff --git a/README.md b/README.md index da64134..974cc45 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# terraform-module-template +# Terraform Module for Service Control Policies Template for Terraform modules ## Providers -No providers. +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | n/a | @@ -34,18 +36,44 @@ No providers. ## Required Inputs -No required inputs. +The following input variables are required: + +### [policies](#input\_policies) + +Description: List of policy configurations + +Type: + +```hcl +list(object({ + name = string + description = string + statements = string # Path to the JSON file containing policy statements + target_ids = list(string) # List of target account IDs or OU IDs + })) +``` ## Optional Inputs -No optional inputs. +The following input variables are optional (have default values): + +### [tags](#input\_tags) + +Description: Tags to apply to all resources created in this module + +Type: `map(string)` + +Default: `{}` ## Outputs -No outputs. +| Name | Description | +|------|-------------| +| [policy\_arns](#output\_policy\_arns) | Map of policy ARNs. | +| [policy\_ids](#output\_policy\_ids) | Map of policy IDs. | diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..3ea6d7a --- /dev/null +++ b/main.tf @@ -0,0 +1,40 @@ +# Loop over each policy to create policy documents dynamically +data "aws_iam_policy_document" "scp_policies" { + for_each = { for p in var.policies : p.name => p } + + dynamic "statement" { + for_each = jsondecode(file(each.value.statements)) + content { + sid = lookup(statement.value, "Sid", null) + effect = lookup(statement.value, "Effect", "Deny") + actions = statement.value.Action + resources = [lookup(statement.value, "Resource", "*")] + + dynamic "condition" { + for_each = lookup(statement.value, "Condition", {}) + content { + test = condition.key + variable = condition.value[0] + values = condition.value[1] + } + } + } + } +} + +# Create policies with tags +resource "aws_organizations_policy" "scp" { + for_each = data.aws_iam_policy_document.scp_policies + name = each.value.name + description = each.value.description + content = each.value.json + tags = var.tags +} + +# Attach policies to targets with tags +resource "aws_organizations_policy_attachment" "attach_scp" { + for_each = { for p in var.policies : p.name => p } + count = length(each.value.target_ids) + policy_id = aws_organizations_policy.scp[each.key].id + target_id = each.value.target_ids[count.index] +} \ No newline at end of file diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..f359b26 --- /dev/null +++ b/outputs.tf @@ -0,0 +1,9 @@ +output "policy_arns" { + value = { for k, v in aws_organizations_policy.scp : k => v.arn } + description = "Map of policy ARNs." +} + +output "policy_ids" { + value = { for k, v in aws_organizations_policy.scp : k => v.id } + description = "Map of policy IDs." +} diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..c111729 --- /dev/null +++ b/variables.tf @@ -0,0 +1,15 @@ +variable "policies" { + description = "List of policy configurations" + type = list(object({ + name = string + description = string + statements = string # Path to the JSON file containing policy statements + target_ids = list(string) # List of target account IDs or OU IDs + })) +} + +variable "tags" { + description = "Tags to apply to all resources created in this module" + type = map(string) + default = {} +}