From 2a4698b032af0993b8012a21b1a643cbde0cb024 Mon Sep 17 00:00:00 2001 From: Lukasz Stadnik Date: Fri, 4 Oct 2024 12:57:19 +0200 Subject: [PATCH 01/13] feat(modules/iam): creat new AWS IAM module --- modules/iam/README.md | 70 ++++++++++++ modules/iam/main.tf | 234 +++++++++++++++++++++++++++++++++++++++ modules/iam/main_test.go | 11 ++ modules/iam/outputs.tf | 9 ++ modules/iam/variables.tf | 153 +++++++++++++++++++++++++ modules/iam/versions.tf | 9 ++ 6 files changed, 486 insertions(+) create mode 100644 modules/iam/README.md create mode 100644 modules/iam/main.tf create mode 100644 modules/iam/main_test.go create mode 100644 modules/iam/outputs.tf create mode 100644 modules/iam/variables.tf create mode 100644 modules/iam/versions.tf diff --git a/modules/iam/README.md b/modules/iam/README.md new file mode 100644 index 0000000..69f0464 --- /dev/null +++ b/modules/iam/README.md @@ -0,0 +1,70 @@ +# Palo Alto Networks IAM Module for AWS + +One instance of module supports one policy type. +IAM Module is policy use-case for: +* lambda policies +* vmseries policy +* spokes with managed AWS SSM +* bootstrap for S3 bucket access +* custom policy + +## Usage + +## Reference + +### Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0.0, < 2.0.0 | +| [aws](#requirement\_aws) | ~> 5.17 | + +### Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | ~> 5.17 | + +### Modules + +No modules. + +### Resources + +| Name | Type | +|------|------| +| [aws_iam_instance_profile.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | +| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | +| [aws_iam_role_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | +| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | +| [aws_iam_policy_document.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_partition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | + +### Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [aws\_s3\_bucket](#input\_aws\_s3\_bucket) | Name of the s3 bucket, that is required and used for
var.create_bootrap_policy
. | `string` | `null` | no | +| [create\_bootrap\_policy](#input\_create\_bootrap\_policy) | Create a pre-defined bootstrap policy. | `bool` | `false` | no | +| [create\_instance\_profile](#input\_create\_instance\_profile) | Create an instance profile. | `bool` | `false` | no | +| [create\_lambda\_policy](#input\_create\_lambda\_policy) | Create a pre-defined lambda policies for ASG. | `bool` | `false` | no | +| [create\_role](#input\_create\_role) | Create a dedicated role creation of pre-defined policies. | `bool` | `true` | no | +| [create\_vmseries\_policy](#input\_create\_vmseries\_policy) | Create a pre-defined vmseries policy. | `bool` | `false` | no | +| [custom\_policy](#input\_custom\_policy) | A custom lambda policy. Multi-statement is supported.
Basic example:
statement1 = {
sid = "1"
effect = "Allow"
actions = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
resources = [
"arn:*:logs:*:*:*"
]
}
statement2 = {
sid = "2"
effect = "Allow"
actions = [
"ec2:AllocateAddress",
"ec2:AssociateAddress",
"ec2:AttachNetworkInterface",
"ec2:CreateNetworkInterface",
"ec2:CreateTags",
"ec2:DescribeAddresses",
"ec2:DescribeInstances",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeTags",
"ec2:DescribeSubnets",
"ec2:DeleteNetworkInterface",
"ec2:DeleteTags",
"ec2:DetachNetworkInterface",
"ec2:DisassociateAddress",
"ec2:ModifyNetworkInterfaceAttribute",
"ec2:ReleaseAddress",
"autoscaling:CompleteLifecycleAction",
"autoscaling:DescribeAutoScalingGroups",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:DeregisterTargets"
]

resources = ["*"]

condition = {
test = "StringEquals"
variable = "aws:ResourceTag/Owner"
values = "user1"
}
}
|
map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
}))
| `null` | no | +| [delicense\_ssm\_param\_name](#input\_delicense\_ssm\_param\_name) | It is required for IAM de-licensing permission IAM settings.
Secure string in Parameter Store with value in below format:
{"username":"ACCOUNT","password":"PASSWORD","panorama1":"IP_ADDRESS1","panorama2":"IP_ADDRESS2","license_manager":"LICENSE_MANAGER_NAME"}"
the format can either be the plain name in case you store it without hierarchy or with a "/" in case you store in in a hierarchy | `string` | `null` | no | +| [global\_tags](#input\_global\_tags) | Global tags configured for all provisioned resources. | `map(any)` | n/a | yes | +| [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources. (IAM Role, Instance Profile) | `string` | n/a | yes | +| [policy\_arn](#input\_policy\_arn) | The AWS or Customer managed policy arn. It should be used for spoke VM scenario using the AWS managed
arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
policy. | `string` | `null` | no | +| [principal\_role](#input\_principal\_role) | The type of entity that can take actions in AWS. | `string` | `"ec2.amazonaws.com"` | no | +| [profile\_instance\_name](#input\_profile\_instance\_name) | A profile instance name. | `string` | `null` | no | +| [region](#input\_region) | AWS region where SSM or CloudWatch is located. | `string` | n/a | yes | +| [role\_name](#input\_role\_name) | A role name, required for the service. | `string` | n/a | yes | + +### Outputs + +| Name | Description | +|------|-------------| +| [iam\_role](#output\_iam\_role) | The role used for policies. | +| [instance\_profile](#output\_instance\_profile) | The instance profile created for VM. | + diff --git a/modules/iam/main.tf b/modules/iam/main.tf new file mode 100644 index 0000000..ae171a7 --- /dev/null +++ b/modules/iam/main.tf @@ -0,0 +1,234 @@ +### IAM ROLES AND POLICIES ### + +data "aws_caller_identity" "this" {} + +data "aws_partition" "this" {} + +locals { + + account_id = data.aws_caller_identity.this.account_id + delicense_param = try(startswith(var.delicense_ssm_param_name, "/") ? var.delicense_ssm_param_name : "/${var.delicense_ssm_param_name}", null) + + lambda_execute_policy = { + statement1 = { + sid = "1" + effect = "Allow" + actions = [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ] + resources = [ + "arn:${data.aws_partition.this.partition}:logs:*:*:*" + ] + } + statement2 = { + sid = "2" + effect = "Allow" + actions = [ + "ec2:AllocateAddress", + "ec2:AssociateAddress", + "ec2:AttachNetworkInterface", + "ec2:CreateNetworkInterface", + "ec2:CreateTags", + "ec2:DescribeAddresses", + "ec2:DescribeInstances", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeTags", + "ec2:DescribeSubnets", + "ec2:DeleteNetworkInterface", + "ec2:DeleteTags", + "ec2:DetachNetworkInterface", + "ec2:DisassociateAddress", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:ReleaseAddress", + "autoscaling:CompleteLifecycleAction", + "autoscaling:DescribeAutoScalingGroups", + "elasticloadbalancing:RegisterTargets", + "elasticloadbalancing:DeregisterTargets" + ] + + resources = ["*"] + + condition = { + test = "StringEquals" + variable = "aws:ResourceTag/Owner" + values = [var.global_tags["Owner"]] + } + } + statement3 = { + sid = "3" + effect = "Allow" + actions = [ + "ec2:DescribeAddresses", + "ec2:DescribeInstances", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeTags", + "ec2:DescribeSubnets", + ] + + resources = ["*"] + } + statement4 = { + sid = "4" + effect = "Allow" + actions = [ + "kms:GenerateDataKey*", + "kms:Decrypt", + "kms:CreateGrant" + ] + + resources = ["*"] + + condition = { + test = "StringEquals" + variable = "aws:ResourceTag/Owner" + values = [var.global_tags["Owner"]] + } + } + } + + lambda_delicense_policy = { + statement1 = { + sid = "1" + effect = "Allow" + actions = [ + "ssm:DescribeParameters", + "ssm:GetParametersByPath", + "ssm:GetParameter", + "ssm:GetParameterHistory" + ] + + resources = [ + "arn:${data.aws_partition.this.partition}:ssm:${var.region}:${local.account_id}:parameter${local.delicense_param}" + ] + } + } + + vmseries_policy = { + statement1 = { + sid = "1" + effect = "Allow" + actions = [ + "cloudwatch:PutMetricData", + "cloudwatch:GetMetricData", + "cloudwatch:ListMetrics" + ] + + resources = [ + "*" + ] + } + statement2 = { + sid = "2" + effect = "Allow" + actions = [ + "cloudwatch:PutMetricAlarm", + "cloudwatch:DescribeAlarms" + ] + + resources = [ + "arn:${data.aws_partition.this.partition}:cloudwatch:${var.region}:${data.aws_caller_identity.this.account_id}:alarm:*" + ] + } + } + + bootstrap_policy = { + statement1 = { + sid = "1" + effect = "Allow" + actions = ["s3:GetObject"] + resources = ["arn:${data.aws_partition.this.partition}:s3:::${var.aws_s3_bucket}"] + } + statement2 = { + sid = "2" + effect = "Allow" + actions = ["s3:GetObject"] + resources = ["arn:${data.aws_partition.this.partition}:s3:::${var.aws_s3_bucket}/*"] + } + } + + aws_policies = { + "custom" = { + enable = var.custom_policy == null ? false : true + definition = try(var.custom_policy, null) + }, + "lambda_execute" = { + enable = var.create_lambda_policy && var.delicense_ssm_param_name != null ? true : false + definition = try(local.lambda_execute_policy, null) + }, + "lambda_delicense" = { + enable = var.create_lambda_policy && var.delicense_ssm_param_name != null ? true : false + definition = try(local.lambda_delicense_policy, null) + }, + "vmseries" = { + enable = var.create_vmseries_policy + definition = try(local.vmseries_policy, null) + }, + "bootstrap" = { + enable = var.create_bootrap_policy && var.aws_s3_bucket != null ? true : false + definition = try(local.bootstrap_policy, null) + } + } +} + +data "aws_iam_policy_document" "this" { + for_each = { for k, v in local.aws_policies : k => v if v.enable == true } + + dynamic "statement" { + for_each = each.value.definition + content { + sid = statement.value["sid"] + effect = statement.value["effect"] + resources = statement.value["resources"] + actions = statement.value["actions"] + dynamic "condition" { + for_each = lookup(statement.value, "condition", {}) != {} ? [1] : [] + content { + test = try(statement.value["condition"]["test"], null) + variable = try(statement.value["condition"]["variable"], null) + values = try(statement.value["condition"]["values"], null) + } + } + } + } +} + +resource "aws_iam_role" "this" { + count = var.create_role ? 1 : 0 + name = "${var.name_prefix}${var.role_name}" + assume_role_policy = <<-EOF +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "${var.principal_role}" + }, + "Action": "sts:AssumeRole" + } + ] +} +EOF +} + +resource "aws_iam_role_policy_attachment" "this" { + count = var.policy_arn == null ? 0 : 1 + role = aws_iam_role.this[0].name + policy_arn = var.policy_arn +} + +resource "aws_iam_role_policy" "this" { + for_each = data.aws_iam_policy_document.this + + name = "${var.name_prefix}${each.key}" + role = aws_iam_role.this[0].id + policy = each.value.json +} + +resource "aws_iam_instance_profile" "this" { + count = var.create_instance_profile ? 1 : 0 + name = "${var.name_prefix}${var.profile_instance_name}" + role = aws_iam_role.this[0].name +} \ No newline at end of file diff --git a/modules/iam/main_test.go b/modules/iam/main_test.go new file mode 100644 index 0000000..d69eccc --- /dev/null +++ b/modules/iam/main_test.go @@ -0,0 +1,11 @@ +package iam + +import ( + "testing" + + "github.com/PaloAltoNetworks/terraform-modules-swfw-tests-skeleton/pkg/testskeleton" +) + +func TestValidate(t *testing.T) { + testskeleton.ValidateCode(t, nil) +} diff --git a/modules/iam/outputs.tf b/modules/iam/outputs.tf new file mode 100644 index 0000000..5abf0ff --- /dev/null +++ b/modules/iam/outputs.tf @@ -0,0 +1,9 @@ +output "instance_profile" { + description = "The instance profile created for VM." + value = var.create_instance_profile ? aws_iam_instance_profile.this : null +} + +output "iam_role" { + description = "The role used for policies." + value = var.create_role ? aws_iam_role.this : null +} \ No newline at end of file diff --git a/modules/iam/variables.tf b/modules/iam/variables.tf new file mode 100644 index 0000000..5ca7df6 --- /dev/null +++ b/modules/iam/variables.tf @@ -0,0 +1,153 @@ +variable "name_prefix" { + description = "Prefix used in names for the resources. (IAM Role, Instance Profile)" + type = string +} + +variable "global_tags" { + description = "Global tags configured for all provisioned resources." + type = map(any) +} + +variable "region" { + description = "AWS region where SSM or CloudWatch is located." + type = string +} + +variable "principal_role" { + description = "The type of entity that can take actions in AWS." + type = string + default = "ec2.amazonaws.com" +} + +variable "create_role" { + description = "Create a dedicated role creation of pre-defined policies." + type = bool + default = true +} + +variable "create_instance_profile" { + description = "Create an instance profile." + type = bool + default = false +} + +variable "profile_instance_name" { + description = "A profile instance name." + type = string + default = null +} + +variable "create_lambda_policy" { + description = "Create a pre-defined lambda policies for ASG." + type = bool + default = false +} + +variable "create_vmseries_policy" { + description = "Create a pre-defined vmseries policy." + type = bool + default = false +} + +variable "create_bootrap_policy" { + description = "Create a pre-defined bootstrap policy." + type = bool + default = false +} + +variable "policy_arn" { + description = "The AWS or Customer managed policy arn. It should be used for spoke VM scenario using the AWS managed ```arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore``` policy." + type = string + default = null # +} + +variable "custom_policy" { + description = <<-EOF + A custom lambda policy. Multi-statement is supported. + Basic example: + ``` + statement1 = { + sid = "1" + effect = "Allow" + actions = [ + "logs:CreateLogGroup", + "logs:CreateLogStream", + "logs:PutLogEvents" + ] + resources = [ + "arn:*:logs:*:*:*" + ] + } + statement2 = { + sid = "2" + effect = "Allow" + actions = [ + "ec2:AllocateAddress", + "ec2:AssociateAddress", + "ec2:AttachNetworkInterface", + "ec2:CreateNetworkInterface", + "ec2:CreateTags", + "ec2:DescribeAddresses", + "ec2:DescribeInstances", + "ec2:DescribeNetworkInterfaces", + "ec2:DescribeTags", + "ec2:DescribeSubnets", + "ec2:DeleteNetworkInterface", + "ec2:DeleteTags", + "ec2:DetachNetworkInterface", + "ec2:DisassociateAddress", + "ec2:ModifyNetworkInterfaceAttribute", + "ec2:ReleaseAddress", + "autoscaling:CompleteLifecycleAction", + "autoscaling:DescribeAutoScalingGroups", + "elasticloadbalancing:RegisterTargets", + "elasticloadbalancing:DeregisterTargets" + ] + + resources = ["*"] + + condition = { + test = "StringEquals" + variable = "aws:ResourceTag/Owner" + values = "user1" + } + } + ``` + EOF + type = map(object({ + sid = string + effect = string + actions = list(string) + resources = list(string) + condition = optional(object({ + test = string + variable = string + values = list(string) + })) + })) + default = null +} + +variable "delicense_ssm_param_name" { + description = <<-EOF + It is required for IAM de-licensing permission IAM settings. + Secure string in Parameter Store with value in below format: + ``` + {"username":"ACCOUNT","password":"PASSWORD","panorama1":"IP_ADDRESS1","panorama2":"IP_ADDRESS2","license_manager":"LICENSE_MANAGER_NAME"}" + ``` + the format can either be the plain name in case you store it without hierarchy or with a "/" in case you store in in a hierarchy + EOF + default = null + type = string +} + +variable "aws_s3_bucket" { + description = "Name of the s3 bucket, that is required and used for ```var.create_bootrap_policy```." + default = null + type = string +} + +variable "role_name" { + description = "A role name, required for the service." + type = string +} \ No newline at end of file diff --git a/modules/iam/versions.tf b/modules/iam/versions.tf new file mode 100644 index 0000000..9ddb384 --- /dev/null +++ b/modules/iam/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.0.0, < 2.0.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.17" + } + } +} From d245764a9e02ededd7dd6f51b895ea24c872f638 Mon Sep 17 00:00:00 2001 From: lstadnik Date: Thu, 24 Oct 2024 11:25:39 +0200 Subject: [PATCH 02/13] Update modules/iam/README.md Co-authored-by: michalbil <92343355+michalbil@users.noreply.github.com> --- modules/iam/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/iam/README.md b/modules/iam/README.md index 69f0464..76526e7 100644 --- a/modules/iam/README.md +++ b/modules/iam/README.md @@ -1,12 +1,12 @@ # Palo Alto Networks IAM Module for AWS -One instance of module supports one policy type. -IAM Module is policy use-case for: -* lambda policies -* vmseries policy -* spokes with managed AWS SSM -* bootstrap for S3 bucket access -* custom policy +One instance of the module is designed to create one policy. +It supports policies for following use cases: +* VM-Series +* S3 based bootstrap +* Lambda +* spokes with managed AWS SSM +* custom policy ## Usage From d58ecfdad2c65e5b8bebbe46e2ac60c509beb060 Mon Sep 17 00:00:00 2001 From: lstadnik Date: Thu, 24 Oct 2024 11:25:49 +0200 Subject: [PATCH 03/13] Update modules/iam/main.tf Co-authored-by: michalbil <92343355+michalbil@users.noreply.github.com> --- modules/iam/main.tf | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/iam/main.tf b/modules/iam/main.tf index ae171a7..ccf60da 100644 --- a/modules/iam/main.tf +++ b/modules/iam/main.tf @@ -5,7 +5,6 @@ data "aws_caller_identity" "this" {} data "aws_partition" "this" {} locals { - account_id = data.aws_caller_identity.this.account_id delicense_param = try(startswith(var.delicense_ssm_param_name, "/") ? var.delicense_ssm_param_name : "/${var.delicense_ssm_param_name}", null) From c5906f20e397470b73d7b7ff6ae224cd93bbe291 Mon Sep 17 00:00:00 2001 From: Lukasz Stadnik Date: Thu, 24 Oct 2024 11:42:14 +0200 Subject: [PATCH 04/13] fix(module/iam): lambda policy --- modules/iam/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/iam/main.tf b/modules/iam/main.tf index ccf60da..5954a18 100644 --- a/modules/iam/main.tf +++ b/modules/iam/main.tf @@ -153,7 +153,7 @@ locals { definition = try(var.custom_policy, null) }, "lambda_execute" = { - enable = var.create_lambda_policy && var.delicense_ssm_param_name != null ? true : false + enable = var.create_lambda_policy ? true : false definition = try(local.lambda_execute_policy, null) }, "lambda_delicense" = { From aaca9efe74621867a3438e1475f98cf862f4709c Mon Sep 17 00:00:00 2001 From: lstadnik Date: Thu, 24 Oct 2024 11:57:11 +0200 Subject: [PATCH 05/13] Typo and formatting Co-authored-by: michalbil <92343355+michalbil@users.noreply.github.com> --- modules/iam/main.tf | 3 +++ modules/iam/variables.tf | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/modules/iam/main.tf b/modules/iam/main.tf index 5954a18..3b84581 100644 --- a/modules/iam/main.tf +++ b/modules/iam/main.tf @@ -195,6 +195,7 @@ data "aws_iam_policy_document" "this" { resource "aws_iam_role" "this" { count = var.create_role ? 1 : 0 + name = "${var.name_prefix}${var.role_name}" assume_role_policy = <<-EOF { @@ -214,6 +215,7 @@ EOF resource "aws_iam_role_policy_attachment" "this" { count = var.policy_arn == null ? 0 : 1 + role = aws_iam_role.this[0].name policy_arn = var.policy_arn } @@ -228,6 +230,7 @@ resource "aws_iam_role_policy" "this" { resource "aws_iam_instance_profile" "this" { count = var.create_instance_profile ? 1 : 0 + name = "${var.name_prefix}${var.profile_instance_name}" role = aws_iam_role.this[0].name } \ No newline at end of file diff --git a/modules/iam/variables.tf b/modules/iam/variables.tf index 5ca7df6..d391a3b 100644 --- a/modules/iam/variables.tf +++ b/modules/iam/variables.tf @@ -31,8 +31,8 @@ variable "create_instance_profile" { default = false } -variable "profile_instance_name" { - description = "A profile instance name." +variable "instance_profile_name" { + description = "Instance profile name." type = string default = null } @@ -130,8 +130,8 @@ variable "custom_policy" { variable "delicense_ssm_param_name" { description = <<-EOF - It is required for IAM de-licensing permission IAM settings. - Secure string in Parameter Store with value in below format: + Required for IAM de-licensing permissions. + String in Parameter Store with value in below format: ``` {"username":"ACCOUNT","password":"PASSWORD","panorama1":"IP_ADDRESS1","panorama2":"IP_ADDRESS2","license_manager":"LICENSE_MANAGER_NAME"}" ``` From bf98ab48c67c731f9fbab6753634e688d50813f5 Mon Sep 17 00:00:00 2001 From: Lukasz Stadnik Date: Thu, 24 Oct 2024 12:04:43 +0200 Subject: [PATCH 06/13] fix(module/iam): rename variable and try --- modules/iam/README.md | 4 ++-- modules/iam/main.tf | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/modules/iam/README.md b/modules/iam/README.md index 76526e7..437ba03 100644 --- a/modules/iam/README.md +++ b/modules/iam/README.md @@ -52,12 +52,12 @@ No modules. | [create\_role](#input\_create\_role) | Create a dedicated role creation of pre-defined policies. | `bool` | `true` | no | | [create\_vmseries\_policy](#input\_create\_vmseries\_policy) | Create a pre-defined vmseries policy. | `bool` | `false` | no | | [custom\_policy](#input\_custom\_policy) | A custom lambda policy. Multi-statement is supported.
Basic example:
statement1 = {
sid = "1"
effect = "Allow"
actions = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
resources = [
"arn:*:logs:*:*:*"
]
}
statement2 = {
sid = "2"
effect = "Allow"
actions = [
"ec2:AllocateAddress",
"ec2:AssociateAddress",
"ec2:AttachNetworkInterface",
"ec2:CreateNetworkInterface",
"ec2:CreateTags",
"ec2:DescribeAddresses",
"ec2:DescribeInstances",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeTags",
"ec2:DescribeSubnets",
"ec2:DeleteNetworkInterface",
"ec2:DeleteTags",
"ec2:DetachNetworkInterface",
"ec2:DisassociateAddress",
"ec2:ModifyNetworkInterfaceAttribute",
"ec2:ReleaseAddress",
"autoscaling:CompleteLifecycleAction",
"autoscaling:DescribeAutoScalingGroups",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:DeregisterTargets"
]

resources = ["*"]

condition = {
test = "StringEquals"
variable = "aws:ResourceTag/Owner"
values = "user1"
}
}
|
map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
}))
| `null` | no | -| [delicense\_ssm\_param\_name](#input\_delicense\_ssm\_param\_name) | It is required for IAM de-licensing permission IAM settings.
Secure string in Parameter Store with value in below format:
{"username":"ACCOUNT","password":"PASSWORD","panorama1":"IP_ADDRESS1","panorama2":"IP_ADDRESS2","license_manager":"LICENSE_MANAGER_NAME"}"
the format can either be the plain name in case you store it without hierarchy or with a "/" in case you store in in a hierarchy | `string` | `null` | no | +| [delicense\_ssm\_param\_name](#input\_delicense\_ssm\_param\_name) | Required for IAM de-licensing permissions.
String in Parameter Store with value in below format:
{"username":"ACCOUNT","password":"PASSWORD","panorama1":"IP_ADDRESS1","panorama2":"IP_ADDRESS2","license_manager":"LICENSE_MANAGER_NAME"}"
the format can either be the plain name in case you store it without hierarchy or with a "/" in case you store in in a hierarchy | `string` | `null` | no | | [global\_tags](#input\_global\_tags) | Global tags configured for all provisioned resources. | `map(any)` | n/a | yes | +| [instance\_profile\_name](#input\_instance\_profile\_name) | Instance profile name. | `string` | `null` | no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources. (IAM Role, Instance Profile) | `string` | n/a | yes | | [policy\_arn](#input\_policy\_arn) | The AWS or Customer managed policy arn. It should be used for spoke VM scenario using the AWS managed
arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
policy. | `string` | `null` | no | | [principal\_role](#input\_principal\_role) | The type of entity that can take actions in AWS. | `string` | `"ec2.amazonaws.com"` | no | -| [profile\_instance\_name](#input\_profile\_instance\_name) | A profile instance name. | `string` | `null` | no | | [region](#input\_region) | AWS region where SSM or CloudWatch is located. | `string` | n/a | yes | | [role\_name](#input\_role\_name) | A role name, required for the service. | `string` | n/a | yes | diff --git a/modules/iam/main.tf b/modules/iam/main.tf index 3b84581..8b6382f 100644 --- a/modules/iam/main.tf +++ b/modules/iam/main.tf @@ -154,19 +154,19 @@ locals { }, "lambda_execute" = { enable = var.create_lambda_policy ? true : false - definition = try(local.lambda_execute_policy, null) + definition = local.lambda_execute_policy }, "lambda_delicense" = { enable = var.create_lambda_policy && var.delicense_ssm_param_name != null ? true : false - definition = try(local.lambda_delicense_policy, null) + definition = local.lambda_delicense_policy }, "vmseries" = { enable = var.create_vmseries_policy - definition = try(local.vmseries_policy, null) + definition = local.vmseries_policy }, "bootstrap" = { enable = var.create_bootrap_policy && var.aws_s3_bucket != null ? true : false - definition = try(local.bootstrap_policy, null) + definition = local.bootstrap_policy } } } @@ -194,8 +194,8 @@ data "aws_iam_policy_document" "this" { } resource "aws_iam_role" "this" { - count = var.create_role ? 1 : 0 - + count = var.create_role ? 1 : 0 + name = "${var.name_prefix}${var.role_name}" assume_role_policy = <<-EOF { @@ -214,8 +214,8 @@ EOF } resource "aws_iam_role_policy_attachment" "this" { - count = var.policy_arn == null ? 0 : 1 - + count = var.policy_arn == null ? 0 : 1 + role = aws_iam_role.this[0].name policy_arn = var.policy_arn } @@ -230,7 +230,7 @@ resource "aws_iam_role_policy" "this" { resource "aws_iam_instance_profile" "this" { count = var.create_instance_profile ? 1 : 0 - - name = "${var.name_prefix}${var.profile_instance_name}" - role = aws_iam_role.this[0].name + + name = "${var.name_prefix}${var.instance_profile_name}" + role = aws_iam_role.this[0].name } \ No newline at end of file From a37af6482d358296db698af4afe677f05e94875e Mon Sep 17 00:00:00 2001 From: Lukasz Stadnik Date: Fri, 25 Oct 2024 09:46:07 +0200 Subject: [PATCH 07/13] feat(iam/example): update iam spoke instance profile --- examples/centralized_design/README.md | 8 +++-- examples/centralized_design/example.tfvars | 6 ++++ examples/centralized_design/main.tf | 37 ++++++---------------- examples/centralized_design/variables.tf | 20 ++++++++++++ modules/iam/README.md | 3 +- modules/iam/main.tf | 14 +++++--- modules/iam/outputs.tf | 4 +-- modules/iam/variables.tf | 3 +- 8 files changed, 56 insertions(+), 39 deletions(-) diff --git a/examples/centralized_design/README.md b/examples/centralized_design/README.md index 23d5972..9fe98cc 100644 --- a/examples/centralized_design/README.md +++ b/examples/centralized_design/README.md @@ -75,6 +75,7 @@ To enable access from the session manager, the Internet connection for a public | [app\_lb](#module\_app\_lb) | ../../modules/nlb | n/a | | [gwlb](#module\_gwlb) | ../../modules/gwlb | n/a | | [gwlbe\_endpoint](#module\_gwlbe\_endpoint) | ../../modules/gwlb_endpoint_set | n/a | +| [iam\_spoke](#module\_iam\_spoke) | ../../modules/iam | n/a | | [natgw\_set](#module\_natgw\_set) | ../../modules/nat_gateway_set | n/a | | [public\_alb](#module\_public\_alb) | ../../modules/alb | n/a | | [public\_nlb](#module\_public\_nlb) | ../../modules/nlb | n/a | @@ -90,12 +91,9 @@ To enable access from the session manager, the Internet connection for a public |------|------| | [aws_ec2_transit_gateway_route.from_security_to_panorama](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | | [aws_ec2_transit_gateway_route.from_spokes_to_security](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | -| [aws_iam_instance_profile.spoke_vm_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | | [aws_iam_instance_profile.vm_series_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_role.spoke_vm_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role.vm_series_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy.vm_series_ec2_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_iam_role_policy_attachment.spoke_vm_iam_instance_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_instance.spoke_vms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | | [aws_lb_target_group_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group_attachment) | resource | | [aws_ami.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | @@ -108,12 +106,16 @@ To enable access from the session manager, the Internet connection for a public | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [create\_instance\_profile](#input\_create\_instance\_profile) | Create an instance profile. | `bool` | `false` | no | | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `gwlb`: key of GWLB
- `vpc`: key of VPC
- `subnet_group`: key of the subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
gwlb = "security_gwlb"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
}
}
|
map(object({
name = string
gwlb = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
}))
| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.

Following properties are available:
- `name`: name of the GWLB
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
gwlbs = {
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | +| [instance\_profile\_name](#input\_instance\_profile\_name) | Instance profile name. | `string` | `null` | no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [natgws](#input\_natgws) | A map defining NAT Gateways.

Following properties are available:
- `name`: name of NAT Gateway
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
natgws = {
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | | [panorama\_attachment](#input\_panorama\_attachment) | A object defining TGW attachment and CIDR for Panorama.

Following properties are available:
- `transit_gateway_attachment_id`: ID of attachment for Panorama
- `vpc_cidr`: CIDR of the VPC, where Panorama is deployed

Example:
panorama = {
transit_gateway_attachment_id = "tgw-attach-123456789"
vpc_cidr = "10.255.0.0/24"
}
|
object({
transit_gateway_attachment_id = string
vpc_cidr = string
})
| `null` | no | +| [policy\_arn](#input\_policy\_arn) | The AWS or Customer managed policy arn. It should be used for spoke VM scenario using the AWS managed
arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
policy. | `string` | `null` | no | | [region](#input\_region) | AWS region used to deploy whole infrastructure | `string` | n/a | yes | +| [role\_name](#input\_role\_name) | A role name, required for the service. | `string` | n/a | yes | | [spoke\_lbs](#input\_spoke\_lbs) | A map defining Network Load Balancers deployed in spoke VPCs.

Following properties are available:
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group
- `vms`: keys of spoke VMs

Example:
spoke_lbs = {
"app1-nlb" = {
vpc = "app1_vpc"
subnet_group = "app1_lb"
vms = ["app1_vm01", "app1_vm02"]
}
}
|
map(object({
vpc = string
subnet_group = string
vms = list(string)
}))
| `{}` | no | | [spoke\_vms](#input\_spoke\_vms) | A map defining VMs in spoke VPCs.

Following properties are available:
- `az`: name of the Availability Zone
- `vpc`: name of the VPC (needs to be one of the keys in map `vpcs`)
- `subnet_group`: key of the subnet\_group
- `security_group`: security group assigned to ENI used by VM
- `type`: EC2 type VM

Example:
spoke_vms = {
"app1_vm01" = {
az = "eu-central-1a"
vpc = "app1_vpc"
subnet_group = "app1_vm"
security_group = "app1_vm"
type = "t2.micro"
}
}
|
map(object({
az = string
vpc = string
subnet_group = string
security_group = string
type = string
}))
| `{}` | no | | [ssh\_key\_name](#input\_ssh\_key\_name) | Name of the SSH key pair existing in AWS key pairs and used to authenticate to VM-Series or test boxes | `string` | n/a | yes | diff --git a/examples/centralized_design/example.tfvars b/examples/centralized_design/example.tfvars index 0174695..4b69e3d 100644 --- a/examples/centralized_design/example.tfvars +++ b/examples/centralized_design/example.tfvars @@ -10,6 +10,12 @@ tags = { ssh_key_name = "example-ssh-key" # TODO: update here +### IAM Spoke definition +create_instance_profile = true +instance_profile_name = "spoke_instance_profile" +role_name = "spoke_role" +policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" + ### VPC vpcs = { security_vpc = { diff --git a/examples/centralized_design/main.tf b/examples/centralized_design/main.tf index 284dc65..e2477c2 100644 --- a/examples/centralized_design/main.tf +++ b/examples/centralized_design/main.tf @@ -313,32 +313,15 @@ data "aws_kms_alias" "current_arn" { name = data.aws_ebs_default_kms_key.current.key_arn } -resource "aws_iam_role" "spoke_vm_ec2_iam_role" { - name = "${var.name_prefix}spoke_vm" - assume_role_policy = < [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources. (IAM Role, Instance Profile) | `string` | n/a | yes | | [policy\_arn](#input\_policy\_arn) | The AWS or Customer managed policy arn. It should be used for spoke VM scenario using the AWS managed
arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
policy. | `string` | `null` | no | | [principal\_role](#input\_principal\_role) | The type of entity that can take actions in AWS. | `string` | `"ec2.amazonaws.com"` | no | -| [region](#input\_region) | AWS region where SSM or CloudWatch is located. | `string` | n/a | yes | +| [region](#input\_region) | AWS region where SSM or CloudWatch is located. | `string` | `null` | no | | [role\_name](#input\_role\_name) | A role name, required for the service. | `string` | n/a | yes | ### Outputs diff --git a/modules/iam/main.tf b/modules/iam/main.tf index 8b6382f..3b2174b 100644 --- a/modules/iam/main.tf +++ b/modules/iam/main.tf @@ -2,11 +2,15 @@ data "aws_caller_identity" "this" {} +data "aws_region" "this" {} + data "aws_partition" "this" {} locals { + region = var.region != null ? var.region : data.aws_region.this.name + aws_s3_bucket = var.aws_s3_bucket != null ? var.aws_s3_bucket : "" account_id = data.aws_caller_identity.this.account_id - delicense_param = try(startswith(var.delicense_ssm_param_name, "/") ? var.delicense_ssm_param_name : "/${var.delicense_ssm_param_name}", null) + delicense_param = try(startswith(var.delicense_ssm_param_name, "/") ? var.delicense_ssm_param_name : "/${var.delicense_ssm_param_name}", "") lambda_execute_policy = { statement1 = { @@ -99,7 +103,7 @@ locals { ] resources = [ - "arn:${data.aws_partition.this.partition}:ssm:${var.region}:${local.account_id}:parameter${local.delicense_param}" + "arn:${data.aws_partition.this.partition}:ssm:${local.region}:${local.account_id}:parameter${local.delicense_param}" ] } } @@ -127,7 +131,7 @@ locals { ] resources = [ - "arn:${data.aws_partition.this.partition}:cloudwatch:${var.region}:${data.aws_caller_identity.this.account_id}:alarm:*" + "arn:${data.aws_partition.this.partition}:cloudwatch:${local.region}:${data.aws_caller_identity.this.account_id}:alarm:*" ] } } @@ -137,13 +141,13 @@ locals { sid = "1" effect = "Allow" actions = ["s3:GetObject"] - resources = ["arn:${data.aws_partition.this.partition}:s3:::${var.aws_s3_bucket}"] + resources = ["arn:${data.aws_partition.this.partition}:s3:::${local.aws_s3_bucket}"] } statement2 = { sid = "2" effect = "Allow" actions = ["s3:GetObject"] - resources = ["arn:${data.aws_partition.this.partition}:s3:::${var.aws_s3_bucket}/*"] + resources = ["arn:${data.aws_partition.this.partition}:s3:::${local.aws_s3_bucket}/*"] } } diff --git a/modules/iam/outputs.tf b/modules/iam/outputs.tf index 5abf0ff..134d008 100644 --- a/modules/iam/outputs.tf +++ b/modules/iam/outputs.tf @@ -1,9 +1,9 @@ output "instance_profile" { description = "The instance profile created for VM." - value = var.create_instance_profile ? aws_iam_instance_profile.this : null + value = var.create_instance_profile ? aws_iam_instance_profile.this[0] : null } output "iam_role" { description = "The role used for policies." - value = var.create_role ? aws_iam_role.this : null + value = var.create_role ? aws_iam_role.this[0] : null } \ No newline at end of file diff --git a/modules/iam/variables.tf b/modules/iam/variables.tf index d391a3b..82eaae4 100644 --- a/modules/iam/variables.tf +++ b/modules/iam/variables.tf @@ -11,6 +11,7 @@ variable "global_tags" { variable "region" { description = "AWS region where SSM or CloudWatch is located." type = string + default = null } variable "principal_role" { @@ -58,7 +59,7 @@ variable "create_bootrap_policy" { variable "policy_arn" { description = "The AWS or Customer managed policy arn. It should be used for spoke VM scenario using the AWS managed ```arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore``` policy." type = string - default = null # + default = null } variable "custom_policy" { From 071538b1d8efe02a2e76c7000a79e5bd49d35c56 Mon Sep 17 00:00:00 2001 From: Lukasz Stadnik Date: Mon, 28 Oct 2024 12:32:46 +0100 Subject: [PATCH 08/13] feat(example/iam): update the example for iam module --- examples/centralized_design/README.md | 10 +-- examples/centralized_design/example.tfvars | 6 -- examples/centralized_design/main.tf | 83 ++++------------------ examples/centralized_design/variables.tf | 35 +++++---- modules/iam/README.md | 2 +- modules/iam/main.tf | 4 +- modules/iam/variables.tf | 12 ++-- 7 files changed, 40 insertions(+), 112 deletions(-) diff --git a/examples/centralized_design/README.md b/examples/centralized_design/README.md index 9fe98cc..43571c2 100644 --- a/examples/centralized_design/README.md +++ b/examples/centralized_design/README.md @@ -91,31 +91,23 @@ To enable access from the session manager, the Internet connection for a public |------|------| | [aws_ec2_transit_gateway_route.from_security_to_panorama](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | | [aws_ec2_transit_gateway_route.from_spokes_to_security](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | -| [aws_iam_instance_profile.vm_series_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_role.vm_series_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.vm_series_ec2_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_instance.spoke_vms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | | [aws_lb_target_group_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group_attachment) | resource | | [aws_ami.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | -| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_ebs_default_kms_key.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ebs_default_kms_key) | data source | | [aws_kms_alias.current_arn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source | -| [aws_partition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | ### Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [create\_instance\_profile](#input\_create\_instance\_profile) | Create an instance profile. | `bool` | `false` | no | | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `gwlb`: key of GWLB
- `vpc`: key of VPC
- `subnet_group`: key of the subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
gwlb = "security_gwlb"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
}
}
|
map(object({
name = string
gwlb = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
}))
| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.

Following properties are available:
- `name`: name of the GWLB
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
gwlbs = {
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | -| [instance\_profile\_name](#input\_instance\_profile\_name) | Instance profile name. | `string` | `null` | no | +| [iam\_policies](#input\_iam\_policies) | A role name, required for the service. | `any` |
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "centralized_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "centralized_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [natgws](#input\_natgws) | A map defining NAT Gateways.

Following properties are available:
- `name`: name of NAT Gateway
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
natgws = {
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | | [panorama\_attachment](#input\_panorama\_attachment) | A object defining TGW attachment and CIDR for Panorama.

Following properties are available:
- `transit_gateway_attachment_id`: ID of attachment for Panorama
- `vpc_cidr`: CIDR of the VPC, where Panorama is deployed

Example:
panorama = {
transit_gateway_attachment_id = "tgw-attach-123456789"
vpc_cidr = "10.255.0.0/24"
}
|
object({
transit_gateway_attachment_id = string
vpc_cidr = string
})
| `null` | no | -| [policy\_arn](#input\_policy\_arn) | The AWS or Customer managed policy arn. It should be used for spoke VM scenario using the AWS managed
arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
policy. | `string` | `null` | no | | [region](#input\_region) | AWS region used to deploy whole infrastructure | `string` | n/a | yes | -| [role\_name](#input\_role\_name) | A role name, required for the service. | `string` | n/a | yes | | [spoke\_lbs](#input\_spoke\_lbs) | A map defining Network Load Balancers deployed in spoke VPCs.

Following properties are available:
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group
- `vms`: keys of spoke VMs

Example:
spoke_lbs = {
"app1-nlb" = {
vpc = "app1_vpc"
subnet_group = "app1_lb"
vms = ["app1_vm01", "app1_vm02"]
}
}
|
map(object({
vpc = string
subnet_group = string
vms = list(string)
}))
| `{}` | no | | [spoke\_vms](#input\_spoke\_vms) | A map defining VMs in spoke VPCs.

Following properties are available:
- `az`: name of the Availability Zone
- `vpc`: name of the VPC (needs to be one of the keys in map `vpcs`)
- `subnet_group`: key of the subnet\_group
- `security_group`: security group assigned to ENI used by VM
- `type`: EC2 type VM

Example:
spoke_vms = {
"app1_vm01" = {
az = "eu-central-1a"
vpc = "app1_vpc"
subnet_group = "app1_vm"
security_group = "app1_vm"
type = "t2.micro"
}
}
|
map(object({
az = string
vpc = string
subnet_group = string
security_group = string
type = string
}))
| `{}` | no | | [ssh\_key\_name](#input\_ssh\_key\_name) | Name of the SSH key pair existing in AWS key pairs and used to authenticate to VM-Series or test boxes | `string` | n/a | yes | diff --git a/examples/centralized_design/example.tfvars b/examples/centralized_design/example.tfvars index 4b69e3d..0174695 100644 --- a/examples/centralized_design/example.tfvars +++ b/examples/centralized_design/example.tfvars @@ -10,12 +10,6 @@ tags = { ssh_key_name = "example-ssh-key" # TODO: update here -### IAM Spoke definition -create_instance_profile = true -instance_profile_name = "spoke_instance_profile" -role_name = "spoke_role" -policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" - ### VPC vpcs = { security_vpc = { diff --git a/examples/centralized_design/main.tf b/examples/centralized_design/main.tf index e2477c2..42bba47 100644 --- a/examples/centralized_design/main.tf +++ b/examples/centralized_design/main.tf @@ -157,67 +157,6 @@ locals { ] } } -### IAM ROLES AND POLICIES ### - -data "aws_caller_identity" "this" {} - -data "aws_partition" "this" {} - -resource "aws_iam_role" "vm_series_ec2_iam_role" { - name = "${var.name_prefix}vmseries" - assume_role_policy = < [create\_vmseries\_policy](#input\_create\_vmseries\_policy) | Create a pre-defined vmseries policy. | `bool` | `false` | no | | [custom\_policy](#input\_custom\_policy) | A custom lambda policy. Multi-statement is supported.
Basic example:
statement1 = {
sid = "1"
effect = "Allow"
actions = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
resources = [
"arn:*:logs:*:*:*"
]
}
statement2 = {
sid = "2"
effect = "Allow"
actions = [
"ec2:AllocateAddress",
"ec2:AssociateAddress",
"ec2:AttachNetworkInterface",
"ec2:CreateNetworkInterface",
"ec2:CreateTags",
"ec2:DescribeAddresses",
"ec2:DescribeInstances",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeTags",
"ec2:DescribeSubnets",
"ec2:DeleteNetworkInterface",
"ec2:DeleteTags",
"ec2:DetachNetworkInterface",
"ec2:DisassociateAddress",
"ec2:ModifyNetworkInterfaceAttribute",
"ec2:ReleaseAddress",
"autoscaling:CompleteLifecycleAction",
"autoscaling:DescribeAutoScalingGroups",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:DeregisterTargets"
]

resources = ["*"]

condition = {
test = "StringEquals"
variable = "aws:ResourceTag/Owner"
values = "user1"
}
}
|
map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
}))
| `null` | no | | [delicense\_ssm\_param\_name](#input\_delicense\_ssm\_param\_name) | Required for IAM de-licensing permissions.
String in Parameter Store with value in below format:
{"username":"ACCOUNT","password":"PASSWORD","panorama1":"IP_ADDRESS1","panorama2":"IP_ADDRESS2","license_manager":"LICENSE_MANAGER_NAME"}"
the format can either be the plain name in case you store it without hierarchy or with a "/" in case you store in in a hierarchy | `string` | `null` | no | -| [global\_tags](#input\_global\_tags) | Global tags configured for all provisioned resources. | `map(any)` | n/a | yes | | [instance\_profile\_name](#input\_instance\_profile\_name) | Instance profile name. | `string` | `null` | no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources. (IAM Role, Instance Profile) | `string` | n/a | yes | | [policy\_arn](#input\_policy\_arn) | The AWS or Customer managed policy arn. It should be used for spoke VM scenario using the AWS managed
arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
policy. | `string` | `null` | no | | [principal\_role](#input\_principal\_role) | The type of entity that can take actions in AWS. | `string` | `"ec2.amazonaws.com"` | no | | [region](#input\_region) | AWS region where SSM or CloudWatch is located. | `string` | `null` | no | | [role\_name](#input\_role\_name) | A role name, required for the service. | `string` | n/a | yes | +| [tags](#input\_tags) | Global tags configured for all provisioned resources. | `map(any)` | n/a | yes | ### Outputs diff --git a/modules/iam/main.tf b/modules/iam/main.tf index 3b2174b..28b19e7 100644 --- a/modules/iam/main.tf +++ b/modules/iam/main.tf @@ -56,7 +56,7 @@ locals { condition = { test = "StringEquals" variable = "aws:ResourceTag/Owner" - values = [var.global_tags["Owner"]] + values = [var.tags["Owner"]] } } statement3 = { @@ -86,7 +86,7 @@ locals { condition = { test = "StringEquals" variable = "aws:ResourceTag/Owner" - values = [var.global_tags["Owner"]] + values = [var.tags["Owner"]] } } } diff --git a/modules/iam/variables.tf b/modules/iam/variables.tf index 82eaae4..dc553a1 100644 --- a/modules/iam/variables.tf +++ b/modules/iam/variables.tf @@ -3,7 +3,7 @@ variable "name_prefix" { type = string } -variable "global_tags" { +variable "tags" { description = "Global tags configured for all provisioned resources." type = map(any) } @@ -26,6 +26,11 @@ variable "create_role" { default = true } +variable "role_name" { + description = "A role name, required for the service." + type = string +} + variable "create_instance_profile" { description = "Create an instance profile." type = bool @@ -147,8 +152,3 @@ variable "aws_s3_bucket" { default = null type = string } - -variable "role_name" { - description = "A role name, required for the service." - type = string -} \ No newline at end of file From 2406ced2bfc83076cb7a10e5906fe7de828ba3a6 Mon Sep 17 00:00:00 2001 From: Lukasz Stadnik Date: Wed, 30 Oct 2024 15:50:21 +0100 Subject: [PATCH 09/13] feat(examples|module): asg and example update against IAM --- examples/centralized_design/README.md | 4 +- examples/centralized_design/main.tf | 34 +++--- examples/centralized_design/variables.tf | 4 +- .../centralized_design_autoscale/README.md | 10 +- examples/centralized_design_autoscale/main.tf | 113 ++++-------------- .../centralized_design_autoscale/variables.tf | 26 ++++ examples/combined_design/README.md | 10 +- examples/combined_design/main.tf | 98 ++------------- examples/combined_design/variables.tf | 21 ++++ examples/combined_design_autoscale/README.md | 10 +- examples/combined_design_autoscale/main.tf | 113 ++++-------------- .../combined_design_autoscale/variables.tf | 26 ++++ examples/isolated_design/README.md | 10 +- examples/isolated_design/main.tf | 109 +++-------------- examples/isolated_design/variables.tf | 21 ++++ examples/isolated_design_autoscale/README.md | 10 +- examples/isolated_design_autoscale/main.tf | 113 ++++-------------- .../isolated_design_autoscale/variables.tf | 26 ++++ modules/asg/README.md | 5 +- modules/asg/main.tf | 107 +---------------- modules/asg/variables.tf | 5 + 21 files changed, 257 insertions(+), 618 deletions(-) diff --git a/examples/centralized_design/README.md b/examples/centralized_design/README.md index 43571c2..77501b7 100644 --- a/examples/centralized_design/README.md +++ b/examples/centralized_design/README.md @@ -75,7 +75,7 @@ To enable access from the session manager, the Internet connection for a public | [app\_lb](#module\_app\_lb) | ../../modules/nlb | n/a | | [gwlb](#module\_gwlb) | ../../modules/gwlb | n/a | | [gwlbe\_endpoint](#module\_gwlbe\_endpoint) | ../../modules/gwlb_endpoint_set | n/a | -| [iam\_spoke](#module\_iam\_spoke) | ../../modules/iam | n/a | +| [iam](#module\_iam) | ../../modules/iam | n/a | | [natgw\_set](#module\_natgw\_set) | ../../modules/nat_gateway_set | n/a | | [public\_alb](#module\_public\_alb) | ../../modules/alb | n/a | | [public\_nlb](#module\_public\_nlb) | ../../modules/nlb | n/a | @@ -103,7 +103,7 @@ To enable access from the session manager, the Internet connection for a public |------|-------------|------|---------|:--------:| | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `gwlb`: key of GWLB
- `vpc`: key of VPC
- `subnet_group`: key of the subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
gwlb = "security_gwlb"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
}
}
|
map(object({
name = string
gwlb = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
}))
| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.

Following properties are available:
- `name`: name of the GWLB
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
gwlbs = {
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | -| [iam\_policies](#input\_iam\_policies) | A role name, required for the service. | `any` |
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "centralized_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "centralized_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "centralized_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "centralized_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [natgws](#input\_natgws) | A map defining NAT Gateways.

Following properties are available:
- `name`: name of NAT Gateway
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
natgws = {
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | | [panorama\_attachment](#input\_panorama\_attachment) | A object defining TGW attachment and CIDR for Panorama.

Following properties are available:
- `transit_gateway_attachment_id`: ID of attachment for Panorama
- `vpc_cidr`: CIDR of the VPC, where Panorama is deployed

Example:
panorama = {
transit_gateway_attachment_id = "tgw-attach-123456789"
vpc_cidr = "10.255.0.0/24"
}
|
object({
transit_gateway_attachment_id = string
vpc_cidr = string
})
| `null` | no | diff --git a/examples/centralized_design/main.tf b/examples/centralized_design/main.tf index 42bba47..1bfb5c6 100644 --- a/examples/centralized_design/main.tf +++ b/examples/centralized_design/main.tf @@ -183,7 +183,7 @@ module "vmseries" { bootstrap_options = join(";", compact(concat(local.bootstrap_options_with_endpoints_mapping[each.value.group]))) - iam_instance_profile = module.iam_spoke["vmseries"].instance_profile.name + iam_instance_profile = module.iam["vmseries"].instance_profile.name ssh_key_name = var.ssh_key_name tags = var.tags @@ -228,6 +228,22 @@ module "public_nlb" { tags = var.tags } +### IAM ### + +module "iam" { + source = "../../modules/iam" + + for_each = var.iam_policies + + name_prefix = var.name_prefix + tags = var.tags + role_name = each.value.role_name + create_instance_profile = try(each.value.create_instance_profile, false) + instance_profile_name = try(each.value.instance_profile_name, null) + policy_arn = try(each.value.policy_arn, null) + create_vmseries_policy = try(each.value.create_vmseries_policy, false) +} + ### SPOKE VM INSTANCES #### data "aws_ami" "this" { @@ -253,20 +269,6 @@ data "aws_kms_alias" "current_arn" { name = data.aws_ebs_default_kms_key.current.key_arn } -module "iam_spoke" { - source = "../../modules/iam" - - for_each = var.iam_policies - - name_prefix = var.name_prefix - tags = var.tags - role_name = each.value.role_name - create_instance_profile = try(each.value.create_instance_profile, null) - instance_profile_name = try(each.value.instance_profile_name, null) - policy_arn = try(each.value.policy_arn, null) - create_vmseries_policy = try(each.value.create_vmseries_policy, null) -} - resource "aws_instance" "spoke_vms" { for_each = var.spoke_vms @@ -276,7 +278,7 @@ resource "aws_instance" "spoke_vms" { subnet_id = module.vpc[each.value.vpc].subnets["${each.value.subnet_group}${each.value.az}"].id vpc_security_group_ids = [module.vpc[each.value.vpc].security_group_ids[each.value.security_group]] tags = merge({ Name = "${var.name_prefix}${each.key}" }, var.tags) - iam_instance_profile = module.iam_spoke["spoke"].instance_profile.name + iam_instance_profile = module.iam["spoke"].instance_profile.name root_block_device { delete_on_termination = true diff --git a/examples/centralized_design/variables.tf b/examples/centralized_design/variables.tf index ea846a0..e98e378 100644 --- a/examples/centralized_design/variables.tf +++ b/examples/centralized_design/variables.tf @@ -14,8 +14,10 @@ variable "ssh_key_name" { description = "Name of the SSH key pair existing in AWS key pairs and used to authenticate to VM-Series or test boxes" type = string } + +### IAM variable "iam_policies" { - description = "A role name, required for the service." + description = "A map defining an IAM policies, roles etc." type = any default = { diff --git a/examples/centralized_design_autoscale/README.md b/examples/centralized_design_autoscale/README.md index 0ce9bc0..76393b5 100644 --- a/examples/centralized_design_autoscale/README.md +++ b/examples/centralized_design_autoscale/README.md @@ -157,6 +157,7 @@ statistic = "Maximum" | [app\_lb](#module\_app\_lb) | ../../modules/nlb | n/a | | [gwlb](#module\_gwlb) | ../../modules/gwlb | n/a | | [gwlbe\_endpoint](#module\_gwlbe\_endpoint) | ../../modules/gwlb_endpoint_set | n/a | +| [iam](#module\_iam) | ../../modules/iam | n/a | | [natgw\_set](#module\_natgw\_set) | ../../modules/nat_gateway_set | n/a | | [public\_alb](#module\_public\_alb) | ../../modules/alb | n/a | | [public\_nlb](#module\_public\_nlb) | ../../modules/nlb | n/a | @@ -172,18 +173,10 @@ statistic = "Maximum" |------|------| | [aws_ec2_transit_gateway_route.from_security_to_panorama](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | | [aws_ec2_transit_gateway_route.from_spokes_to_security](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | -| [aws_iam_instance_profile.spoke_vm_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_instance_profile.vm_series_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_role.spoke_vm_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role.vm_series_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.vm_series_ec2_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_iam_role_policy_attachment.spoke_vm_iam_instance_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_instance.spoke_vms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | | [aws_ami.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | -| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_ebs_default_kms_key.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ebs_default_kms_key) | data source | | [aws_kms_alias.current_arn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source | -| [aws_partition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | ### Inputs @@ -191,6 +184,7 @@ statistic = "Maximum" |------|-------------|------|---------|:--------:| | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `gwlb`: key of GWLB
- `vpc`: key of VPC
- `subnet_group`: key of the subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
gwlb = "security_gwlb"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
}
}
|
map(object({
name = string
gwlb = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
}))
| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.

Following properties are available:
- `name`: name of the GWLB
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
gwlbs = {
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"lambda": {
"create_lambda_policy": true,
"delicense_ssm_param_name": "secret_name",
"principal_role": "lambda.amazonaws.com",
"role_name": "lambda_role"
},
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "centralized_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "centralized_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [natgws](#input\_natgws) | A map defining NAT Gateways.

Following properties are available:
- `name`: name of NAT Gateway
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
natgws = {
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | | [panorama\_attachment](#input\_panorama\_attachment) | A object defining TGW attachment and CIDR for Panorama.

Following properties are available:
- `transit_gateway_attachment_id`: ID of attachment for Panorama
- `vpc_cidr`: CIDR of the VPC, where Panorama is deployed

Example:
panorama = {
transit_gateway_attachment_id = "tgw-attach-123456789"
vpc_cidr = "10.255.0.0/24"
}
|
object({
transit_gateway_attachment_id = string
vpc_cidr = string
})
| `null` | no | diff --git a/examples/centralized_design_autoscale/main.tf b/examples/centralized_design_autoscale/main.tf index 6c3e6be..992de85 100644 --- a/examples/centralized_design_autoscale/main.tf +++ b/examples/centralized_design_autoscale/main.tf @@ -147,67 +147,6 @@ locals { ] } } -### IAM ROLES AND POLICIES ### - -data "aws_caller_identity" "this" {} - -data "aws_partition" "this" {} - -resource "aws_iam_role" "vm_series_ec2_iam_role" { - name = "${var.name_prefix}vmseries" - assume_role_policy = < [gwlb](#module\_gwlb) | ../../modules/gwlb | n/a | | [gwlbe\_endpoint](#module\_gwlbe\_endpoint) | ../../modules/gwlb_endpoint_set | n/a | +| [iam](#module\_iam) | ../../modules/iam | n/a | | [natgw\_set](#module\_natgw\_set) | ../../modules/nat_gateway_set | n/a | | [public\_alb](#module\_public\_alb) | ../../modules/alb | n/a | | [public\_nlb](#module\_public\_nlb) | ../../modules/nlb | n/a | @@ -124,19 +125,11 @@ If no errors occurred during deployment, configure the VM-Series machines as exp |------|------| | [aws_ec2_transit_gateway_route.from_security_to_panorama](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | | [aws_ec2_transit_gateway_route.from_spokes_to_security](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | -| [aws_iam_instance_profile.spoke_vm_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_instance_profile.vm_series_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_role.spoke_vm_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role.vm_series_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.vm_series_ec2_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_iam_role_policy_attachment.spoke_vm_iam_instance_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_instance.spoke_vms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | | [aws_lb_target_group_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group_attachment) | resource | | [aws_ami.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | -| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_ebs_default_kms_key.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ebs_default_kms_key) | data source | | [aws_kms_alias.current_arn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source | -| [aws_partition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | ### Inputs @@ -144,6 +137,7 @@ If no errors occurred during deployment, configure the VM-Series machines as exp |------|-------------|------|---------|:--------:| | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `gwlb`: key of GWLB
- `vpc`: key of VPC
- `subnet_group`: key of the subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
gwlb = "security_gwlb"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
}
}
|
map(object({
name = string
gwlb = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
}))
| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.

Following properties are available:
- `name`: name of the GWLB
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
gwlbs = {
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "combined_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "combined_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [natgws](#input\_natgws) | A map defining NAT Gateways.

Following properties are available:
- `name`: name of NAT Gateway
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
natgws = {
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | | [panorama\_attachment](#input\_panorama\_attachment) | An object defining TGW attachment and CIDR for Panorama.


Following properties are available:
- `transit_gateway_attachment_id`: ID of attachment for Panorama
- `vpc_cidr`: CIDR of the VPC, where Panorama is deployed

Example:
panorama = {
transit_gateway_attachment_id = "tgw-attach-123456789"
vpc_cidr = "10.255.0.0/24"
}
|
object({
transit_gateway_attachment_id = string
vpc_cidr = string
})
| `null` | no | diff --git a/examples/combined_design/main.tf b/examples/combined_design/main.tf index 3ea935c..41f5046 100644 --- a/examples/combined_design/main.tf +++ b/examples/combined_design/main.tf @@ -157,65 +157,21 @@ locals { ] } } -### IAM ROLES AND POLICIES ### - -data "aws_caller_identity" "this" {} - -data "aws_partition" "this" {} - -resource "aws_iam_role" "vm_series_ec2_iam_role" { - name = "${var.name_prefix}vmseries" - assume_role_policy = < [app\_lb](#module\_app\_lb) | ../../modules/nlb | n/a | | [gwlb](#module\_gwlb) | ../../modules/gwlb | n/a | | [gwlbe\_endpoint](#module\_gwlbe\_endpoint) | ../../modules/gwlb_endpoint_set | n/a | +| [iam](#module\_iam) | ../../modules/iam | n/a | | [natgw\_set](#module\_natgw\_set) | ../../modules/nat_gateway_set | n/a | | [transit\_gateway](#module\_transit\_gateway) | ../../modules/transit_gateway | n/a | | [transit\_gateway\_attachment](#module\_transit\_gateway\_attachment) | ../../modules/transit_gateway_attachment | n/a | @@ -244,18 +245,10 @@ To enable access from the session manager, the Internet connection for a public |------|------| | [aws_ec2_transit_gateway_route.from_security_to_panorama](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | | [aws_ec2_transit_gateway_route.from_spokes_to_security](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | -| [aws_iam_instance_profile.spoke_vm_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_instance_profile.vm_series_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_role.spoke_vm_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role.vm_series_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.vm_series_ec2_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_iam_role_policy_attachment.spoke_vm_iam_instance_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_instance.spoke_vms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | | [aws_ami.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | -| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_ebs_default_kms_key.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ebs_default_kms_key) | data source | | [aws_kms_alias.current_arn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source | -| [aws_partition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | ### Inputs @@ -263,6 +256,7 @@ To enable access from the session manager, the Internet connection for a public |------|-------------|------|---------|:--------:| | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `gwlb`: key of GWLB
- `vpc`: key of VPC
- `subnet_group`: key of subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
gwlb = "security_gwlb"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
}
}
|
map(object({
name = string
gwlb = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
}))
| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.

Following properties are available:
- `name`: name of the GWLB
- `vpc`: VPC key
- `subnet_group`: subnet\_group key

Example:
gwlbs = {
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"lambda": {
"create_lambda_policy": true,
"delicense_ssm_param_name": "secret_name",
"principal_role": "lambda.amazonaws.com",
"role_name": "lambda_role"
},
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "combined_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "combined_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [natgws](#input\_natgws) | A map defining NAT Gateways.

Following properties are available:
- `name`: name of NAT Gateway
- `vpc`: VPC key
- `subnet_group`: subnet\_group key

Example:
natgws = {
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | | [panorama\_attachment](#input\_panorama\_attachment) | A object defining TGW attachment and CIDR for Panorama.

Following properties are available:
- `transit_gateway_attachment_id`: ID of attachment for Panorama
- `vpc_cidr`: CIDR of the VPC, where Panorama is deployed

Example:
panorama = {
transit_gateway_attachment_id = "tgw-attach-123456789"
vpc_cidr = "10.255.0.0/24"
}
|
object({
transit_gateway_attachment_id = string
vpc_cidr = string
})
| `null` | no | diff --git a/examples/combined_design_autoscale/main.tf b/examples/combined_design_autoscale/main.tf index f74447b..03ffc9f 100644 --- a/examples/combined_design_autoscale/main.tf +++ b/examples/combined_design_autoscale/main.tf @@ -147,67 +147,6 @@ locals { ] } } -### IAM ROLES AND POLICIES ### - -data "aws_caller_identity" "this" {} - -data "aws_partition" "this" {} - -resource "aws_iam_role" "vm_series_ec2_iam_role" { - name = "${var.name_prefix}vmseries" - assume_role_policy = < [gwlb](#module\_gwlb) | ../../modules/gwlb | n/a | | [gwlbe\_endpoint](#module\_gwlbe\_endpoint) | ../../modules/gwlb_endpoint_set | n/a | +| [iam](#module\_iam) | ../../modules/iam | n/a | | [public\_alb](#module\_public\_alb) | ../../modules/alb | n/a | | [public\_nlb](#module\_public\_nlb) | ../../modules/nlb | n/a | | [vmseries](#module\_vmseries) | ../../modules/vmseries | n/a | @@ -90,20 +91,12 @@ To enable access from the session manager, the Internet connection for a public | Name | Type | |------|------| -| [aws_iam_instance_profile.spoke_vm_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_instance_profile.vm_series_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_role.spoke_vm_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role.vm_series_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.vm_series_ec2_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_iam_role_policy_attachment.spoke_vm_iam_instance_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_instance.spoke_vms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | | [aws_lb_target_group_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lb_target_group_attachment) | resource | | [aws_vpc_peering_connection.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_peering_connection) | resource | | [aws_ami.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | -| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_ebs_default_kms_key.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ebs_default_kms_key) | data source | | [aws_kms_alias.current_arn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source | -| [aws_partition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | ### Inputs @@ -111,6 +104,7 @@ To enable access from the session manager, the Internet connection for a public |------|-------------|------|---------|:--------:| | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `gwlb`: key of GWLB
- `vpc`: key of VPC
- `subnet_group`: key of subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
gwlb = "security_gwlb"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
}
}
|
map(object({
name = string
gwlb = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
}))
| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.

Following properties are available:
- `name`: name of the GWLB
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
gwlbs = {
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "isolated_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "isolated_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [panorama\_connection](#input\_panorama\_connection) | A object defining VPC peering and CIDR for Panorama.

Following properties are available:
- `security_vpc`: key of the security VPC
- `peering_vpc_id`: ID of the VPC for Panorama
- `vpc_cidr`: CIDR of the VPC, where Panorama is deployed

Example:
panorama = {
security_vpc = "security_vpc"
peering_vpc_id = "vpc-1234567890"
vpc_cidr = "10.255.0.0/24"
}
|
object({
security_vpc = string
peering_vpc_id = string
vpc_cidr = string
})
| `null` | no | | [region](#input\_region) | AWS region used to deploy whole infrastructure | `string` | n/a | yes | diff --git a/examples/isolated_design/main.tf b/examples/isolated_design/main.tf index 7afb4b1..78f3364 100644 --- a/examples/isolated_design/main.tf +++ b/examples/isolated_design/main.tf @@ -116,67 +116,6 @@ locals { ] } } -### IAM ROLES AND POLICIES ### - -data "aws_caller_identity" "this" {} - -data "aws_partition" "this" {} - -resource "aws_iam_role" "vm_series_ec2_iam_role" { - name = "${var.name_prefix}vmseries" - assume_role_policy = < [gwlb](#module\_gwlb) | ../../modules/gwlb | n/a | | [gwlbe\_endpoint](#module\_gwlbe\_endpoint) | ../../modules/gwlb_endpoint_set | n/a | +| [iam](#module\_iam) | ../../modules/iam | n/a | | [public\_alb](#module\_public\_alb) | ../../modules/alb | n/a | | [public\_nlb](#module\_public\_nlb) | ../../modules/nlb | n/a | | [vm\_series\_asg](#module\_vm\_series\_asg) | ../../modules/asg | n/a | @@ -198,19 +199,11 @@ statistic = "Maximum" | Name | Type | |------|------| -| [aws_iam_instance_profile.spoke_vm_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_instance_profile.vm_series_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_role.spoke_vm_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role.vm_series_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.vm_series_ec2_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_iam_role_policy_attachment.spoke_vm_iam_instance_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_instance.spoke_vms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | | [aws_vpc_peering_connection.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc_peering_connection) | resource | | [aws_ami.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | -| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_ebs_default_kms_key.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ebs_default_kms_key) | data source | | [aws_kms_alias.current_arn](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_alias) | data source | -| [aws_partition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | ### Inputs @@ -218,6 +211,7 @@ statistic = "Maximum" |------|-------------|------|---------|:--------:| | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `gwlb`: key of GWLB
- `vpc`: key of VPC
- `subnet_group`: key of the subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
gwlb = "security_gwlb"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
}
}
|
map(object({
name = string
gwlb = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
}))
| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.

Following properties are available:
- `name`: name of the GWLB
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
gwlbs = {
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"lambda": {
"create_lambda_policy": true,
"delicense_ssm_param_name": "secret_name",
"principal_role": "lambda.amazonaws.com",
"role_name": "lambda_role"
},
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "isolated_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "isolated_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [panorama\_connection](#input\_panorama\_connection) | A object defining VPC peering and CIDR for Panorama.

Following properties are available:
- `security_vpc`: key of the security VPC
- `peering_vpc_id`: ID of the VPC for Panorama
- `vpc_cidr`: CIDR of the VPC, where Panorama is deployed

Example:
panorama = {
security_vpc = "security_vpc"
peering_vpc_id = "vpc-1234567890"
vpc_cidr = "10.255.0.0/24"
}
|
object({
security_vpc = string
peering_vpc_id = string
vpc_cidr = string
})
| `null` | no | | [region](#input\_region) | AWS region used to deploy whole infrastructure | `string` | n/a | yes | diff --git a/examples/isolated_design_autoscale/main.tf b/examples/isolated_design_autoscale/main.tf index 1c1dde4..a5dbd70 100644 --- a/examples/isolated_design_autoscale/main.tf +++ b/examples/isolated_design_autoscale/main.tf @@ -106,67 +106,6 @@ locals { ] } } -### IAM ROLES AND POLICIES ### - -data "aws_caller_identity" "this" {} - -data "aws_partition" "this" {} - -resource "aws_iam_role" "vm_series_ec2_iam_role" { - name = "${var.name_prefix}vmseries" - assume_role_policy = < [interfaces](#input\_interfaces) | Map of the network interface specifications.
If "mgmt-interface-swap" bootstrap option is enabled, ensure dataplane interface `device_index` is set to 0 and the firewall management interface `device_index` is set to 1.
Available options:
- `device_index` = (Required\|int) Determines order in which interfaces are attached to the instance. Interface with `0` is attached at boot time.
- `subnet_id` = (Required\|string) Subnet ID to create the ENI in.
- `name` = (Optional\|string) Name tag for the ENI. Defaults to instance name suffixed by map's key.
- `description` = (Optional\|string) A descriptive name for the ENI.
- `create_public_ip` = (Optional\|bool) Whether to create a public IP for the ENI. Defaults to false.
- `eip_allocation_id` = (Optional\|string) Associate an existing EIP to the ENI.
- `private_ips` = (Optional\|list) List of private IPs to assign to the ENI. If not set, dynamic allocation is used.
- `public_ipv4_pool` = (Optional\|string) EC2 IPv4 address pool identifier.
- `source_dest_check` = (Optional\|bool) Whether to enable source destination checking for the ENI. Defaults to false.
- `security_group_ids` = (Optional\|list) A list of Security Group IDs to assign to this interface. Defaults to null.

Example:
interfaces = {
mgmt = {
device_index = 0
subnet_id = aws_subnet.mgmt.id
name = "mgmt"
create_public_ip = true
source_dest_check = true
security_group_ids = ["sg-123456"]
},
public = {
device_index = 1
subnet_id = aws_subnet.public.id
name = "public"
create_public_ip = true
},
private = {
device_index = 2
subnet_id = aws_subnet.private.id
name = "private"
},
]
| `map(any)` | n/a | yes | | [ip\_target\_groups](#input\_ip\_target\_groups) | Target groups (type IP) for load balancers, which are used by Lamda to register VM-Series IP of untrust interface |
list(object({
arn = string
port = string
}))
| `[]` | no | | [lambda\_execute\_pip\_install\_once](#input\_lambda\_execute\_pip\_install\_once) | Flag used in local-exec command installing Python packages required by Lambda.

If set to true, local-exec is executed only once, when all resources are created.
If you need to have idempotent behaviour for terraform apply every time and you have downloaded
all required Python packages, set it to true.

If set to false, every time it's checked if files for package pan\_os\_python are downloaded.
If not, it causes execution of local-exec command in two consecutive calls of terraform apply:
- first time value of installed-pan-os-python is changed from true (or empty) to false
- second time value of installed-pan-os-python is changed from false to true
In summary while executing code from scratch, two consecutive calls of terraform apply are not idempotent.
The third execution of terraform apply show no changes.
While using modules in CI/CD pipelines, when agents are selected randomly, set this value to false
in order to check every time, if pan\_os\_python package is downloaded. sdfdsf sdfvars | `bool` | `false` | no | +| [lambda\_role\_arn](#input\_lambda\_role\_arn) | IAM Role for lambda instnace. | `string` | n/a | yes | | [lambda\_timeout](#input\_lambda\_timeout) | Amount of time Lambda Function has to run in seconds. | `number` | `30` | no | | [launch\_template\_update\_default\_version](#input\_launch\_template\_update\_default\_version) | Whether to update launch template default version each update.

If set to true, every time when e.g. bootstrap options are changed, new version is created and default version is updated.
If set to false, every time when e.g. bootstrap options are changed, new version is created, but default version is not changed. | `bool` | `true` | no | | [launch\_template\_version](#input\_launch\_template\_version) | Launch template version to use to launch instances | `string` | `"$Latest"` | no | diff --git a/modules/asg/main.tf b/modules/asg/main.tf index 0ce2d7d..fb5728f 100644 --- a/modules/asg/main.tf +++ b/modules/asg/main.tf @@ -176,111 +176,6 @@ resource "aws_autoscaling_group" "this" { ] } -# Lookup information about the current AWS partition in which Terraform is working (e.g. `aws`, `aws-us-gov`, `aws-cn`) -data "aws_partition" "this" {} - -# IAM role that will be used for Lambda function -resource "aws_iam_role" "this" { - name = "${var.name_prefix}lambda_iam_role" - assume_role_policy = < Date: Thu, 31 Oct 2024 11:59:35 +0100 Subject: [PATCH 10/13] feat(example/module): introduce panorama iam policy, refactor examples --- examples/panorama_standalone/README.md | 14 +--- examples/panorama_standalone/main.tf | 84 +++---------------- examples/panorama_standalone/variables.tf | 15 ++++ examples/vmseries_standalone/README.md | 14 ++-- examples/vmseries_standalone/example.tfvars | 2 + .../vmseries_standalone/example_ipv6.tfvars | 2 + examples/vmseries_standalone/main.tf | 53 ++++-------- examples/vmseries_standalone/variables.tf | 22 +++++ modules/bootstrap/README.md | 11 --- modules/bootstrap/main.tf | 63 -------------- modules/bootstrap/outputs.tf | 15 ---- modules/bootstrap/variables.tf | 18 ---- modules/iam/README.md | 1 + modules/iam/main.tf | 43 ++++++++++ modules/iam/variables.tf | 6 ++ 15 files changed, 125 insertions(+), 238 deletions(-) diff --git a/examples/panorama_standalone/README.md b/examples/panorama_standalone/README.md index 0d730d0..c6df6c2 100644 --- a/examples/panorama_standalone/README.md +++ b/examples/panorama_standalone/README.md @@ -65,32 +65,26 @@ Use a web browser to access https://x.x.x.x and login with admin and your previo ### Providers -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | ~> 5.17 | +No providers. ### Modules | Name | Source | Version | |------|--------|---------| +| [iam](#module\_iam) | ../../modules/iam | n/a | | [panorama](#module\_panorama) | ../../modules/panorama | n/a | | [vpc](#module\_vpc) | ../../modules/vpc | n/a | | [vpc\_routes](#module\_vpc\_routes) | ../../modules/vpc_route | n/a | ### Resources -| Name | Type | -|------|------| -| [aws_iam_instance_profile.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | -| [aws_partition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | +No resources. ### Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"panorama": {
"create_instance_profile": true,
"create_panorama_policy": true,
"instance_profile_name": "panorama_profile",
"role_name": "panorama_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | `""` | no | | [panoramas](#input\_panoramas) | A map defining Panorama instances

Following properties are available:
- `instances`: map of Panorama instances with attributes:
- `az`: name of the Availability Zone
- `private_ip_address`: private IP address for management interface
- `panos_version`: PAN-OS version used for Panorama
- `network`: definition of network settings in object with attributes:
- `vpc`: name of the VPC (needs to be one of the keys in map `vpcs`)
- `subnet_group` - key of the subnet group
- `security_group`: security group assigned to ENI used by Panorama
- `create_public_ip`: true, if public IP address for management should be created
- `ebs`: EBS settings defined in object with attributes:
- `volumes`: list of EBS volumes attached to each instance
- `kms_key_alias`: KMS key alias used for encrypting Panorama EBS
- `iam`: IAM settings in object with attrbiutes:
- `create_role`: enable creation of IAM role
- `role_name`: name of the role to create or use existing one
- `enable_imdsv2`: whether to enable IMDSv2 on the EC2 instance

Example:
{
panorama_ha_pair = {
instances = {
"primary" = {
az = "eu-central-1a"
private_ip_address = "10.255.0.4"
}
"secondary" = {
az = "eu-central-1b"
private_ip_address = "10.255.1.4"
}
}

panos_version = "10.2.3"

network = {
vpc = "management_vpc"
subnet_group = "mgmt"
security_group = "panorama_mgmt"
create_public_ip = true
}

ebs = {
volumes = [
{
name = "ebs-1"
ebs_device_name = "/dev/sdb"
ebs_size = "2000"
ebs_encrypted = true
},
{
name = "ebs-2"
ebs_device_name = "/dev/sdc"
ebs_size = "2000"
ebs_encrypted = true
}
]
kms_key_alias = "aws/ebs"
}

iam = {
create_role = true
role_name = "panorama"
}

enable_imdsv2 = false
}
}
|
map(object({
instances = map(object({
az = string
private_ip_address = string
}))

panos_version = string

network = object({
vpc = string
subnet_group = string
security_group = string
create_public_ip = bool
})

ebs = object({
volumes = list(object({
name = string
ebs_device_name = string
ebs_size = string
}))
encrypted = bool
kms_key_alias = string
})

iam = object({
create_role = bool
role_name = string
})

enable_imdsv2 = bool
}))
| `{}` | no | | [region](#input\_region) | AWS region used to deploy whole infrastructure | `string` | n/a | yes | diff --git a/examples/panorama_standalone/main.tf b/examples/panorama_standalone/main.tf index 508a615..dd86487 100644 --- a/examples/panorama_standalone/main.tf +++ b/examples/panorama_standalone/main.tf @@ -35,77 +35,19 @@ module "vpc_routes" { internet_gateway_id = each.value.next_hop_type == "internet_gateway" ? module.vpc[each.value.next_hop_key].internet_gateway.id : null } -### IAM ROLES AND POLICIES ### - -data "aws_caller_identity" "this" {} - -data "aws_partition" "this" {} - -resource "aws_iam_role" "this" { - for_each = var.panoramas - name = "${var.name_prefix}${each.value.iam.role_name}" - description = "Allow read-only access to AWS resources." - assume_role_policy = < panorama } - name = "${var.name_prefix}${each.key}panorama_instance_profile" - role = each.value.common.iam.create_role ? aws_iam_role.this[each.value.group].name : each.value.common.iam.role_name + name_prefix = var.name_prefix + tags = var.tags + role_name = each.value.role_name + create_instance_profile = try(each.value.create_instance_profile, false) + instance_profile_name = try(each.value.instance_profile_name, null) + create_panorama_policy = try(each.value.create_panorama_policy, false) } ### PANORAMA INSTANCES @@ -136,12 +78,8 @@ module "panorama" { ebs_kms_key_alias = each.value.common.ebs.kms_key_alias subnet_id = module.vpc[each.value.common.network.vpc].subnets["${each.value.common.network.subnet_group}${each.value.az}"].id vpc_security_group_ids = [module.vpc[each.value.common.network.vpc].security_group_ids[each.value.common.network.security_group]] - panorama_iam_role = aws_iam_instance_profile.this[each.key].name + panorama_iam_role = module.iam["panorama"].instance_profile.name enable_imdsv2 = each.value.common.enable_imdsv2 global_tags = var.tags - - depends_on = [ - aws_iam_instance_profile.this - ] } diff --git a/examples/panorama_standalone/variables.tf b/examples/panorama_standalone/variables.tf index 2f1bf4a..de1b0f0 100644 --- a/examples/panorama_standalone/variables.tf +++ b/examples/panorama_standalone/variables.tf @@ -18,6 +18,21 @@ variable "ssh_key_name" { type = string } +### IAM +variable "iam_policies" { + description = "A map defining an IAM policies, roles etc." + type = any + + default = { + panorama = { + create_instance_profile = true + instance_profile_name = "panorama_profile" + role_name = "panorama_role" + create_panorama_policy = true + } + } +} + ### VPC variable "vpcs" { description = <<-EOF diff --git a/examples/vmseries_standalone/README.md b/examples/vmseries_standalone/README.md index 9ef1765..88cfdbb 100644 --- a/examples/vmseries_standalone/README.md +++ b/examples/vmseries_standalone/README.md @@ -81,36 +81,32 @@ Use a web browser to access https://x.x.x.x and login with admin and your previo ### Providers -| Name | Version | -|------|---------| -| [aws](#provider\_aws) | ~> 5.17 | +No providers. ### Modules | Name | Source | Version | |------|--------|---------| | [bootstrap](#module\_bootstrap) | ../../modules/bootstrap | n/a | +| [iam](#module\_iam) | ../../modules/iam | n/a | | [vmseries](#module\_vmseries) | ../../modules/vmseries | n/a | | [vpc](#module\_vpc) | ../../modules/vpc | n/a | | [vpc\_routes](#module\_vpc\_routes) | ../../modules/vpc_route | n/a | ### Resources -| Name | Type | -|------|------| -| [aws_iam_role_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_caller_identity.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | -| [aws_partition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | +No resources. ### Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"vmseries": {
"aws_s3_bucket": "bucket-paloaltonetworks",
"create_bootrap_policy": true,
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "vmseries_profile_instance",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [region](#input\_region) | AWS region used to deploy whole infrastructure | `string` | n/a | yes | | [ssh\_key\_name](#input\_ssh\_key\_name) | Name of the SSH key pair existing in AWS key pairs and used to authenticate to VM-Series or test boxes | `string` | n/a | yes | | [tags](#input\_tags) | Tags configured for all provisioned resources | `any` | n/a | yes | -| [vmseries](#input\_vmseries) | A map defining VM-Series instances
Following properties are available:
- `instances`: map of VM-Series instances
- `bootstrap_options`: VM-Seriess bootstrap options used to connect to Panorama
- `panos_version`: PAN-OS version used for VM-Series
- `ebs_kms_id`: alias for AWS KMS used for EBS encryption in VM-Series
- `vpc`: key of VPC
Example:
vmseries = {
vmseries = {
instances = {
"01" = { az = "eu-central-1a" }
}
# Value of `panorama-server`, `auth-key`, `dgname`, `tplname` can be taken from plugin `sw_fw_license`
bootstrap_options = {
mgmt-interface-swap = "enable"
plugin-op-commands = "panorama-licensing-mode-on,aws-gwlb-inspect:enable,aws-gwlb-overlay-routing:enable"
dhcp-send-hostname = "yes"
dhcp-send-client-id = "yes"
dhcp-accept-server-hostname = "yes"
dhcp-accept-server-domain = "yes"
}
panos_version = "10.2.3" # TODO: update here
ebs_kms_id = "alias/aws/ebs" # TODO: update here

# Value of `vpc` must match key of objects stored in `vpcs`
vpc = "security_vpc"

interfaces = {
mgmt = {
device_index = 1
private_ip = "10.100.0.4"
security_group = "vmseries_mgmt"
vpc = "security_vpc"
subnet_group = "mgmt"
create_public_ip = true
source_dest_check = true
eip_allocation_id = null
}
}
}
}
|
map(object({
instances = map(object({
az = string
}))

bootstrap_options = object({
mgmt-interface-swap = string
panorama-server = string
tplname = string
dgname = string
plugin-op-commands = string
dhcp-send-hostname = string
dhcp-send-client-id = string
dhcp-accept-server-hostname = string
dhcp-accept-server-domain = string
})

panos_version = string
ebs_kms_id = string

vpc = string

interfaces = map(object({
device_index = number
security_group = string
vpc = string
subnet_group = string
create_public_ip = bool
private_ip = map(string)
ipv6_address_count = number
source_dest_check = bool
eip_allocation_id = map(string)
}))
}))
| `{}` | no | +| [vmseries](#input\_vmseries) | A map defining VM-Series instances
Following properties are available:
- `instances`: map of VM-Series instances
- `bootstrap_options`: VM-Seriess bootstrap options used to connect to Panorama
- `panos_version`: PAN-OS version used for VM-Series
- `ebs_kms_id`: alias for AWS KMS used for EBS encryption in VM-Series
- `vpc`: key of VPC
Example:
vmseries = {
vmseries = {
instances = {
"01" = { az = "eu-central-1a" }
}

bucket_name = "bucket_name"

# Value of `panorama-server`, `auth-key`, `dgname`, `tplname` can be taken from plugin `sw_fw_license`
bootstrap_options = {
mgmt-interface-swap = "enable"
plugin-op-commands = "panorama-licensing-mode-on,aws-gwlb-inspect:enable,aws-gwlb-overlay-routing:enable"
dhcp-send-hostname = "yes"
dhcp-send-client-id = "yes"
dhcp-accept-server-hostname = "yes"
dhcp-accept-server-domain = "yes"
}
panos_version = "10.2.3" # TODO: update here
ebs_kms_id = "alias/aws/ebs" # TODO: update here

# Value of `vpc` must match key of objects stored in `vpcs`
vpc = "security_vpc"

interfaces = {
mgmt = {
device_index = 1
private_ip = "10.100.0.4"
security_group = "vmseries_mgmt"
vpc = "security_vpc"
subnet_group = "mgmt"
create_public_ip = true
source_dest_check = true
eip_allocation_id = null
}
}
}
}
|
map(object({
instances = map(object({
az = string
}))

bucket_name = string

bootstrap_options = object({
mgmt-interface-swap = string
panorama-server = string
tplname = string
dgname = string
plugin-op-commands = string
dhcp-send-hostname = string
dhcp-send-client-id = string
dhcp-accept-server-hostname = string
dhcp-accept-server-domain = string
})

panos_version = string
ebs_kms_id = string

vpc = string

interfaces = map(object({
device_index = number
security_group = string
vpc = string
subnet_group = string
create_public_ip = bool
private_ip = map(string)
ipv6_address_count = number
source_dest_check = bool
eip_allocation_id = map(string)
}))
}))
| `{}` | no | | [vpcs](#input\_vpcs) | A map defining VPCs with security groups and subnets.

Following properties are available:
- `name`: VPC name
- `cidr_block`: Object containing the IPv4 and IPv6 CIDR blocks to assign to a new VPC
- `subnets`: map of subnets with properties
- `routes`: map of routes with properties
- `nacls`: map of network ACLs
- `security_groups`: map of security groups

Example:
vpcs = {
app1_vpc = {
name = "app1-spoke-vpc"
cidr_block = {
ipv4 = "10.104.0.0/16"
}
subnets = {
app1_vma = { az = "a", cidr_block = "10.104.0.0/24", subnet_group = "app1_vm", name = "app1_vm1" }
app1_vmb = { az = "b", cidr_block = "10.104.128.0/24", subnet_group = "app1_vm", name = "app1_vm2" }
app1_lba = { az = "a", cidr_block = "10.104.2.0/24", subnet_group = "app1_lb", name = "app1_lb1" }
app1_lbb = { az = "b", cidr_block = "10.104.130.0/24", subnet_group = "app1_lb", name = "app1_lb2" }
app1_gwlbea = { az = "a", cidr_block = "10.104.3.0/24", subnet_group = "app1_gwlbe", name = "app1_gwlbe1" }
app1_gwlbeb = { az = "b", cidr_block = "10.104.131.0/24", subnet_group = "app1_gwlbe", name = "app1_gwlbe2" }
}
routes = {
vm_default = {
vpc = "app1_vpc"
subnet_group = "app1_vm"
to_cidr = "0.0.0.0/0"
next_hop_key = "app1"
next_hop_type = "transit_gateway_attachment"
}
gwlbe_default = {
vpc = "app1_vpc"
subnet_group = "app1_gwlbe"
to_cidr = "0.0.0.0/0"
next_hop_key = "app1_vpc"
next_hop_type = "internet_gateway"
}
lb_default = {
vpc = "app1_vpc"
subnet_group = "app1_lb"
to_cidr = "0.0.0.0/0"
next_hop_key = "app1_inbound"
next_hop_type = "gwlbe_endpoint"
}
}
nacls = {}
security_groups = {
app1_vm = {
name = "app1_vm"
rules = {
all_outbound = {
description = "Permit All traffic outbound"
type = "egress", from_port = "0", to_port = "0", protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
ssh = {
description = "Permit SSH"
type = "ingress", from_port = "22", to_port = "22", protocol = "tcp"
cidr_blocks = ["0.0.0.0/0", "10.104.0.0/16", "10.105.0.0/16"]
}
https = {
description = "Permit HTTPS"
type = "ingress", from_port = "443", to_port = "443", protocol = "tcp"
cidr_blocks = ["0.0.0.0/0", "10.104.0.0/16", "10.105.0.0/16"]
}
http = {
description = "Permit HTTP"
type = "ingress", from_port = "80", to_port = "80", protocol = "tcp"
cidr_blocks = ["0.0.0.0/0", "10.104.0.0/16", "10.105.0.0/16"]
}
}
}
}
}
}
|
map(object({
name = string
cidr_block = object({
ipv4 = optional(string)
secondary_ipv4 = optional(list(string), [])
assign_generated_ipv6 = optional(bool, false)
})
nacls = map(object({
name = string
rules = map(object({
rule_number = number
type = string
protocol = string
action = string
cidr_block = string
from_port = optional(string)
to_port = optional(string)
}))
}))
security_groups = map(object({
name = string
description = optional(string, "Security group managed by Terraform")
rules = map(object({
description = string
type = string
from_port = string
to_port = string
protocol = string
cidr_blocks = optional(list(string), [])
ipv6_cidr_blocks = optional(list(string))
}))
}))
subnets = map(object({
subnet_group = string
az = string
name = string
cidr_block = string
ipv6_cidr_block = optional(string)
ipv6_index = optional(number)
nacl = optional(string)
create_subnet = optional(bool, true)
create_route_table = optional(bool, true)
existing_route_table_id = optional(string)
associate_route_table = optional(bool, true)
route_table_name = optional(string)
local_tags = optional(map(string), {})
tags = optional(map(string), {})
}))
routes = map(object({
route_table = string
to_cidr = string
az = string
destination_type = string
next_hop_type = string
next_hop_key = string
}))
}))
| `{}` | no | ### Outputs diff --git a/examples/vmseries_standalone/example.tfvars b/examples/vmseries_standalone/example.tfvars index 545401b..26cd6ac 100644 --- a/examples/vmseries_standalone/example.tfvars +++ b/examples/vmseries_standalone/example.tfvars @@ -67,6 +67,8 @@ vmseries = { "01" = { az = "a" } } + bucket_name = "bucket-paloaltonetworks" + # Value of `panorama-server`, `auth-key`, `dgname`, `tplname` can be taken from plugin `sw_fw_license` bootstrap_options = { mgmt-interface-swap = "disable" diff --git a/examples/vmseries_standalone/example_ipv6.tfvars b/examples/vmseries_standalone/example_ipv6.tfvars index 0b17c77..ed8bbd7 100644 --- a/examples/vmseries_standalone/example_ipv6.tfvars +++ b/examples/vmseries_standalone/example_ipv6.tfvars @@ -91,6 +91,8 @@ vmseries = { "01" = { az = "a" } } + bucket_name = "bucket-paloaltonetworks" + # Value of `panorama-server`, `auth-key`, `dgname`, `tplname` can be taken from plugin `sw_fw_license` bootstrap_options = { mgmt-interface-swap = "disable" diff --git a/examples/vmseries_standalone/main.tf b/examples/vmseries_standalone/main.tf index 014cb3b..0484fc4 100644 --- a/examples/vmseries_standalone/main.tf +++ b/examples/vmseries_standalone/main.tf @@ -36,44 +36,21 @@ module "vpc_routes" { internet_gateway_id = each.value.next_hop_type == "internet_gateway" ? module.vpc[each.value.next_hop_key].internet_gateway.id : null } -### IAM ROLES AND POLICIES ### +### IAM ### -data "aws_caller_identity" "this" {} +module "iam" { + source = "../../modules/iam" -data "aws_partition" "this" {} + for_each = var.iam_policies -resource "aws_iam_role_policy" "this" { - for_each = { for vmseries in local.vmseries_instances : "${vmseries.group}-${vmseries.instance}" => vmseries } - role = module.bootstrap[each.key].iam_role_name - policy = < vmseries } - iam_role_name = "${var.name_prefix}vmseries${each.value.instance}" - iam_instance_profile_name = "${var.name_prefix}vmseries_instance_profile${each.value.instance}" - prefix = var.name_prefix bootstrap_options = merge(each.value.common.bootstrap_options, { hostname = "${var.name_prefix}${each.key}" }) source_root_directory = "files" + bucket_name = try(each.value.common.bucket_name, null) } ### VM-Series INSTANCES @@ -124,7 +99,7 @@ module "vmseries" { ["mgmt-interface-swap=${each.value.common.bootstrap_options["mgmt-interface-swap"]}"], ))) - iam_instance_profile = module.bootstrap[each.key].instance_profile_name + iam_instance_profile = module.iam["vmseries"].instance_profile.name ssh_key_name = var.ssh_key_name tags = var.tags } diff --git a/examples/vmseries_standalone/variables.tf b/examples/vmseries_standalone/variables.tf index 55d90aa..70f66a0 100644 --- a/examples/vmseries_standalone/variables.tf +++ b/examples/vmseries_standalone/variables.tf @@ -15,6 +15,23 @@ variable "ssh_key_name" { type = string } +### IAM +variable "iam_policies" { + description = "A map defining an IAM policies, roles etc." + type = any + + default = { + vmseries = { + create_instance_profile = true + instance_profile_name = "vmseries_profile_instance" + role_name = "vmseries_role" + create_vmseries_policy = true + create_bootrap_policy = true + aws_s3_bucket = "bucket-paloaltonetworks" + } + } +} + ### VPC variable "vpcs" { description = <<-EOF @@ -176,6 +193,9 @@ variable "vmseries" { instances = { "01" = { az = "eu-central-1a" } } + + bucket_name = "bucket_name" + # Value of `panorama-server`, `auth-key`, `dgname`, `tplname` can be taken from plugin `sw_fw_license` bootstrap_options = { mgmt-interface-swap = "enable" @@ -213,6 +233,8 @@ variable "vmseries" { az = string })) + bucket_name = string + bootstrap_options = object({ mgmt-interface-swap = string panorama-server = string diff --git a/modules/bootstrap/README.md b/modules/bootstrap/README.md index e8fb0dd..fb5b1df 100644 --- a/modules/bootstrap/README.md +++ b/modules/bootstrap/README.md @@ -91,9 +91,6 @@ No modules. | Name | Type | |------|------| -| [aws_iam_instance_profile.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.bootstrap](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | | [aws_s3_bucket_ownership_controls.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_ownership_controls) | resource | | [aws_s3_bucket_public_access_block.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block) | resource | @@ -103,8 +100,6 @@ No modules. | [aws_s3_object.bootstrap_files](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_object) | resource | | [aws_s3_object.init_cfg](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_object) | resource | | [random_id.sufix](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | -| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_role) | data source | -| [aws_partition.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | | [aws_s3_bucket.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/s3_bucket) | data source | ### Inputs @@ -115,11 +110,8 @@ No modules. | [bootstrap\_options](#input\_bootstrap\_options) | Object define bootstrap options used in the init-cfg.txt file.

There are available bootstrap parameters:
- `hostname` - (`string`, optional) The hostname of the VM-series instance.
- `panorama-server` - (`string`, optional) The FQDN or IP address of the primary Panorama server.
- `panorama-server-2` - (`string`, optional) The FQDN or IP address of the secondary Panorama server.
- `tplname` - (`string`, optional) The Panorama template stack name.
- `dgname` - (`string`, optional) The Panorama device group name.
- `cgname` - (`string`, optional) The Panorama collector group name.
- `dns-primary` - (`string`, optional) The IP address of the primary DNS server.
- `dns-secondary` - (`string`, optional) The IP address of the secondary DNS server.
- `auth-key` - (`string`, optional) VM-Series authentication key generated via plugin sw\_fw\_license.
- `vm-auth-key` - (`string`, optional) VM-Series authentication key generated on Panorama.
- `op-command-modes` - (`string`, optional) Set jumbo-frame and/or mgmt-interface-swap.
- `plugin-op-commands` - (`string`, optional) Set plugin-op-commands.
- `dhcp-send-hostname` - (`string`, optional) The DHCP server determines a value of yes or no. If yes, the firewall sends its hostname to the DHCP server.
- `dhcp-send-client-id` - (`string`, optional) The DHCP server determines a value of yes or no. If yes, the firewall sends its client ID to the DHCP server.
- `dhcp-accept-server-hostname` - (`string`, optional) The DHCP server determines a value of yes or no. If yes, the firewall accepts its hostname from the DHCP server.
- `dhcp-accept-server-domain` - (`string`, optional) The DHCP server determines a value of yes or no. If yes, the firewall accepts its DNS server from the DHCP server. | `any` |
{
"dhcp-accept-server-domain": "yes",
"dhcp-accept-server-hostname": "yes",
"dhcp-send-client-id": "yes",
"dhcp-send-hostname": "yes"
}
| no | | [bucket\_name](#input\_bucket\_name) | Name of a bucket to reuse or create (depending on `create_bucket` value). In the latter case - if empty, the name will be auto-generated. | `string` | `""` | no | | [create\_bucket](#input\_create\_bucket) | If true, a new bucket will be created. When false, name of existing bucket to use has to be provided in `bucket_name` variable. | `bool` | `true` | no | -| [create\_iam\_role\_policy](#input\_create\_iam\_role\_policy) | If true, a new IAM role with policy will be created. When false, name of existing IAM role to use has to be provided in `iam_role_name` variable. | `bool` | `true` | no | | [force\_destroy](#input\_force\_destroy) | Set to false to prevent Terraform from destroying a bucket with unknown objects or locked objects. | `bool` | `true` | no | | [global\_tags](#input\_global\_tags) | Map of arbitrary tags to apply to all resources. | `map(any)` | `{}` | no | -| [iam\_instance\_profile\_name](#input\_iam\_instance\_profile\_name) | Name of the instance profile to create. If empty, name will be auto-generated. | `string` | `""` | no | -| [iam\_role\_name](#input\_iam\_role\_name) | Name of a IAM role to reuse or create (depending on `create_iam_role_policy` value). | `string` | `null` | no | | [prefix](#input\_prefix) | The prefix to use for bucket name, IAM role name, and IAM role policy name. It is allowed to use dash "-" as the last character. | `string` | `"bootstrap-"` | no | | [source\_root\_directory](#input\_source\_root\_directory) | The source directory to become the bucket's root directory. If empty uses `files` subdirectory of a Terraform configuration root directory. | `string` | `""` | no | @@ -131,9 +123,6 @@ No modules. | [bucket\_id](#output\_bucket\_id) | AWS identifier of the bucket. | | [bucket\_name](#output\_bucket\_name) | Name of the bucket. | | [bucket\_regional\_domain\_name](#output\_bucket\_regional\_domain\_name) | Regional domain name of the bucket. | -| [iam\_role\_arn](#output\_iam\_role\_arn) | ARN of created or used IAM role | -| [iam\_role\_name](#output\_iam\_role\_name) | Name of created or used IAM role | -| [instance\_profile\_name](#output\_instance\_profile\_name) | Name of created IAM instance profile. | ## References diff --git a/modules/bootstrap/main.tf b/modules/bootstrap/main.tf index 9046417..a6812d8 100644 --- a/modules/bootstrap/main.tf +++ b/modules/bootstrap/main.tf @@ -6,8 +6,6 @@ locals { random_name = "${var.prefix}${random_id.sufix.hex}" bucket_name = coalesce(var.bucket_name, local.random_name) aws_s3_bucket = var.create_bucket ? aws_s3_bucket.this[0] : data.aws_s3_bucket.this[0] - iam_role_name = coalesce(var.iam_role_name, local.random_name) - aws_iam_role = var.create_iam_role_policy ? aws_iam_role.this[0] : data.aws_iam_role.this[0] } data "aws_s3_bucket" "this" { @@ -89,64 +87,3 @@ resource "aws_s3_object" "bootstrap_files" { key = each.value source = "${local.source_root_directory}/${each.value}" } - -data "aws_iam_role" "this" { - count = var.create_iam_role_policy == false && var.iam_role_name != null ? 1 : 0 - - name = var.iam_role_name -} - -# Lookup information about the current AWS partition in which Terraform is working (e.g. `aws`, `aws-us-gov`, `aws-cn`) -data "aws_partition" "this" {} - -resource "aws_iam_role" "this" { - count = var.create_iam_role_policy ? 1 : 0 - - name = local.iam_role_name - - tags = var.global_tags - assume_role_policy = < [create\_bootrap\_policy](#input\_create\_bootrap\_policy) | Create a pre-defined bootstrap policy. | `bool` | `false` | no | | [create\_instance\_profile](#input\_create\_instance\_profile) | Create an instance profile. | `bool` | `false` | no | | [create\_lambda\_policy](#input\_create\_lambda\_policy) | Create a pre-defined lambda policies for ASG. | `bool` | `false` | no | +| [create\_panorama\_policy](#input\_create\_panorama\_policy) | Create a pre-defined panorama policy. | `bool` | `false` | no | | [create\_role](#input\_create\_role) | Create a dedicated role creation of pre-defined policies. | `bool` | `true` | no | | [create\_vmseries\_policy](#input\_create\_vmseries\_policy) | Create a pre-defined vmseries policy. | `bool` | `false` | no | | [custom\_policy](#input\_custom\_policy) | A custom lambda policy. Multi-statement is supported.
Basic example:
statement1 = {
sid = "1"
effect = "Allow"
actions = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
resources = [
"arn:*:logs:*:*:*"
]
}
statement2 = {
sid = "2"
effect = "Allow"
actions = [
"ec2:AllocateAddress",
"ec2:AssociateAddress",
"ec2:AttachNetworkInterface",
"ec2:CreateNetworkInterface",
"ec2:CreateTags",
"ec2:DescribeAddresses",
"ec2:DescribeInstances",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeTags",
"ec2:DescribeSubnets",
"ec2:DeleteNetworkInterface",
"ec2:DeleteTags",
"ec2:DetachNetworkInterface",
"ec2:DisassociateAddress",
"ec2:ModifyNetworkInterfaceAttribute",
"ec2:ReleaseAddress",
"autoscaling:CompleteLifecycleAction",
"autoscaling:DescribeAutoScalingGroups",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:DeregisterTargets"
]

resources = ["*"]

condition = {
test = "StringEquals"
variable = "aws:ResourceTag/Owner"
values = "user1"
}
}
|
map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
}))
| `null` | no | diff --git a/modules/iam/main.tf b/modules/iam/main.tf index 28b19e7..4a3ee77 100644 --- a/modules/iam/main.tf +++ b/modules/iam/main.tf @@ -151,6 +151,45 @@ locals { } } + panorama_policy = { + statement1 = { + sid = "1" + effect = "Allow" + actions = [ + "ec2:DescribeInstanceStatus", + "ec2:DescribeInstances" + ] + + resources = [ + "*" + ] + } + statement2 = { + sid = "2" + effect = "Allow" + actions = [ + "cloudwatch:ListMetrics", + "cloudwatch:GetMetricStatistics", + "cloudwatch:DescribeAlarmsForMetric" + ] + + resources = [ + "*" + ] + } + statement3 = { + sid = "3" + effect = "Allow" + actions = [ + "cloudwatch:DescribeAlarms" + ] + + resources = [ + "arn:${data.aws_partition.this.partition}:cloudwatch:${local.region}:${data.aws_caller_identity.this.account_id}:alarm:*" + ] + } + } + aws_policies = { "custom" = { enable = var.custom_policy == null ? false : true @@ -172,6 +211,10 @@ locals { enable = var.create_bootrap_policy && var.aws_s3_bucket != null ? true : false definition = local.bootstrap_policy } + "panorama" = { + enable = var.create_panorama_policy ? true : false + definition = local.panorama_policy + } } } diff --git a/modules/iam/variables.tf b/modules/iam/variables.tf index dc553a1..647d76c 100644 --- a/modules/iam/variables.tf +++ b/modules/iam/variables.tf @@ -61,6 +61,12 @@ variable "create_bootrap_policy" { default = false } +variable "create_panorama_policy" { + description = "Create a pre-defined panorama policy." + type = bool + default = false +} + variable "policy_arn" { description = "The AWS or Customer managed policy arn. It should be used for spoke VM scenario using the AWS managed ```arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore``` policy." type = string From 5c4b8519ea056e808f69a23ba81be26331325cab Mon Sep 17 00:00:00 2001 From: Lukasz Stadnik Date: Thu, 7 Nov 2024 10:51:04 +0100 Subject: [PATCH 11/13] feat(example/cloudngfw*): Add IAM module in cloudngfw examples --- examples/cloudngfw_combined_design/README.md | 5 +-- examples/cloudngfw_combined_design/main.tf | 45 +++++++------------ .../cloudngfw_combined_design/variables.tf | 15 +++++++ examples/cloudngfw_isolated_design/README.md | 5 +-- examples/cloudngfw_isolated_design/main.tf | 45 +++++++------------ .../cloudngfw_isolated_design/variables.tf | 16 +++++++ examples/panorama_standalone/example.tfvars | 2 +- 7 files changed, 68 insertions(+), 65 deletions(-) diff --git a/examples/cloudngfw_combined_design/README.md b/examples/cloudngfw_combined_design/README.md index 37bf431..716a1b4 100644 --- a/examples/cloudngfw_combined_design/README.md +++ b/examples/cloudngfw_combined_design/README.md @@ -101,6 +101,7 @@ To enable access from the session manager, the Internet connection for a public |------|--------|---------| | [cloudngfw](#module\_cloudngfw) | ../../modules/cloudngfw | n/a | | [gwlbe\_endpoint](#module\_gwlbe\_endpoint) | ../../modules/gwlb_endpoint_set | n/a | +| [iam](#module\_iam) | ../../modules/iam | n/a | | [natgw\_set](#module\_natgw\_set) | ../../modules/nat_gateway_set | n/a | | [public\_alb](#module\_public\_alb) | ../../modules/alb | n/a | | [public\_nlb](#module\_public\_nlb) | ../../modules/nlb | n/a | @@ -114,9 +115,6 @@ To enable access from the session manager, the Internet connection for a public | Name | Type | |------|------| | [aws_ec2_transit_gateway_route.from_spokes_to_security](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_route) | resource | -| [aws_iam_instance_profile.spoke_vm_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_role.spoke_vm_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy_attachment.spoke_vm_iam_instance_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_instance.spoke_vms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | | [aws_ami.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | @@ -129,6 +127,7 @@ To enable access from the session manager, the Internet connection for a public |------|-------------|------|---------|:--------:| | [cloudngfws](#input\_cloudngfws) | A map defining Cloud NGFWs.

Following properties are available:
- `name` : name of CloudNGFW
- `vpc` : key of the VPC
- `subnet_group` : group of subnets
- `description` : Use for internal purposes.
- `security_rules`: Security Rules definition.
- `log_profiles` : Log Profile definition.

Example:
cloudngfws = {
cloudngfws_security = {
name = "cloudngfw01"
vpc = "app_vpc"
subnet_group = "app_gwlbe"
description = "description"
security_rules =
{
rule_1 = {
rule_list = "LocalRule"
priority = 3
name = "tf-security-rule"
description = "Also configured by Terraform"
source_cidrs = ["any"]
destination_cidrs = ["0.0.0.0/0"]
negate_destination = false
protocol = "application-default"
applications = ["any"]
category_feeds = null
category_url_category_names = null
action = "Allow"
logging = true
audit_comment = "initial config"
}
}
log_profiles = {
dest_1 = {
create_cw = true
name = "PaloAltoCloudNGFW"
destination_type = "CloudWatchLogs"
log_type = "THREAT"
}
dest_2 = {
create_cw = true
name = "PaloAltoCloudNGFW"
destination_type = "CloudWatchLogs"
log_type = "TRAFFIC"
}
dest_3 = {
create_cw = true
name = "PaloAltoCloudNGFW"
destination_type = "CloudWatchLogs"
log_type = "DECRYPTION"
}
}
profile_config = {
anti_spyware = "BestPractice"
anti_virus = "BestPractice"
vulnerability = "BestPractice"
file_blocking = "BestPractice"
url_filtering = "BestPractice"
}
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
description = string
security_rules = map(any)
log_profiles = map(any)
profile_config = map(any)
}))
| `{}` | no | | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `vpc`: key of VPC
- `subnet_group`: key of the subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint
- `delay`: delay in seconds for the endpoint
- `cloudngfw`: key of the Cloud NGFW

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
delay = 60
cloudngfw = "cloudngfw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
delay = number
cloudngfw = string
}))
| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "combined_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [natgws](#input\_natgws) | A map defining NAT Gateways.

Following properties are available:
- `name`: name of NAT Gateway
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
natgws = {
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | | [provider\_account](#input\_provider\_account) | The AWS Account where the resources should be deployed. | `string` | n/a | yes | diff --git a/examples/cloudngfw_combined_design/main.tf b/examples/cloudngfw_combined_design/main.tf index 6f72420..d6d5ce5 100644 --- a/examples/cloudngfw_combined_design/main.tf +++ b/examples/cloudngfw_combined_design/main.tf @@ -128,6 +128,21 @@ module "gwlbe_endpoint" { } : {} } +### IAM ### + +module "iam" { + source = "../../modules/iam" + + for_each = var.iam_policies + + name_prefix = var.name_prefix + tags = var.tags + role_name = each.value.role_name + create_instance_profile = try(each.value.create_instance_profile, false) + instance_profile_name = try(each.value.instance_profile_name, null) + policy_arn = try(each.value.policy_arn, null) +} + ### SPOKE VM INSTANCES #### data "aws_ami" "this" { @@ -153,34 +168,6 @@ data "aws_kms_alias" "current_arn" { name = data.aws_ebs_default_kms_key.current.key_arn } -resource "aws_iam_role" "spoke_vm_ec2_iam_role" { - name = "${var.name_prefix}spoke_vm" - assume_role_policy = < [cloudngfw](#module\_cloudngfw) | ../../modules/cloudngfw | n/a | | [gwlbe\_endpoint](#module\_gwlbe\_endpoint) | ../../modules/gwlb_endpoint_set | n/a | +| [iam](#module\_iam) | ../../modules/iam | n/a | | [natgw\_set](#module\_natgw\_set) | ../../modules/nat_gateway_set | n/a | | [public\_alb](#module\_public\_alb) | ../../modules/alb | n/a | | [public\_nlb](#module\_public\_nlb) | ../../modules/nlb | n/a | @@ -110,9 +111,6 @@ To enable access from the session manager, the Internet connection for a public | Name | Type | |------|------| -| [aws_iam_instance_profile.spoke_vm_iam_instance_profile](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_instance_profile) | resource | -| [aws_iam_role.spoke_vm_ec2_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy_attachment.spoke_vm_iam_instance_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource | | [aws_instance.spoke_vms](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource | | [aws_ami.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | @@ -125,6 +123,7 @@ To enable access from the session manager, the Internet connection for a public |------|-------------|------|---------|:--------:| | [cloudngfws](#input\_cloudngfws) | A map defining Cloud NGFWs.

Following properties are available:
- `name` : name of CloudNGFW
- `vpc` : key of the VPC
- `subnet_group` : group of subnets
- `description` : Use for internal purposes.
- `security_rules`: Security Rules definition.
- `log_profiles` : Log Profile definition.

Example:
cloudngfws = {
cloudngfws_security = {
name = "cloudngfw01"
vpc = "app_vpc"
subnet_group = "app_gwlbe"
description = "description"
security_rules =
{
rule_1 = {
rule_list = "LocalRule"
priority = 3
name = "tf-security-rule"
description = "Also configured by Terraform"
source_cidrs = ["any"]
destination_cidrs = ["0.0.0.0/0"]
negate_destination = false
protocol = "application-default"
applications = ["any"]
category_feeds = null
category_url_category_names = null
action = "Allow"
logging = true
audit_comment = "initial config"
}
}
log_profiles = {
dest_1 = {
create_cw = true
name = "PaloAltoCloudNGFW"
destination_type = "CloudWatchLogs"
log_type = "THREAT"
}
dest_2 = {
create_cw = true
name = "PaloAltoCloudNGFW"
destination_type = "CloudWatchLogs"
log_type = "TRAFFIC"
}
dest_3 = {
create_cw = true
name = "PaloAltoCloudNGFW"
destination_type = "CloudWatchLogs"
log_type = "DECRYPTION"
}
}
profile_config = {
anti_spyware = "BestPractice"
anti_virus = "BestPractice"
vulnerability = "BestPractice"
file_blocking = "BestPractice"
url_filtering = "BestPractice"
}
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
description = string
security_rules = map(any)
log_profiles = map(any)
profile_config = map(any)
}))
| `{}` | no | | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `vpc`: key of VPC
- `subnet_group`: key of the subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint
- `to_vpc`: VPC to which traffic from GWLB endpoint is routed to
- `to_subnet_group`: subnet\_group to which traffic from GWLB endpoint is routed to
- `delay`: delay in seconds for the endpoint
- `cloudngfw`: key of the Cloud NGFW

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
delay = 60
cloudngfw = "cloudngfw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
to_vpc = optional(string)
to_subnet_group = optional(string)
delay = number
cloudngfw = string
}))
| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "isolated_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [natgws](#input\_natgws) | A map defining NAT Gateways.

Following properties are available:
- `name`: name of NAT Gateway
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
natgws = {
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | | [provider\_account](#input\_provider\_account) | The AWS Account where the resources should be deployed. | `string` | n/a | yes | diff --git a/examples/cloudngfw_isolated_design/main.tf b/examples/cloudngfw_isolated_design/main.tf index 4e473ac..53649ca 100644 --- a/examples/cloudngfw_isolated_design/main.tf +++ b/examples/cloudngfw_isolated_design/main.tf @@ -92,6 +92,21 @@ module "gwlbe_endpoint" { } : {} } +### IAM ### + +module "iam" { + source = "../../modules/iam" + + for_each = var.iam_policies + + name_prefix = var.name_prefix + tags = var.tags + role_name = each.value.role_name + create_instance_profile = try(each.value.create_instance_profile, false) + instance_profile_name = try(each.value.instance_profile_name, null) + policy_arn = try(each.value.policy_arn, null) +} + ### SPOKE VM INSTANCES #### data "aws_ami" "this" { @@ -117,34 +132,6 @@ data "aws_kms_alias" "current_arn" { name = data.aws_ebs_default_kms_key.current.key_arn } -resource "aws_iam_role" "spoke_vm_ec2_iam_role" { - name = "${var.name_prefix}spoke_vm" - assume_role_policy = < Date: Wed, 18 Dec 2024 12:58:22 +0100 Subject: [PATCH 12/13] feat(modules/iam): bump up terraform and fix desc --- modules/iam/variables.tf | 2 +- modules/iam/versions.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/iam/variables.tf b/modules/iam/variables.tf index 647d76c..34b6c2d 100644 --- a/modules/iam/variables.tf +++ b/modules/iam/variables.tf @@ -75,7 +75,7 @@ variable "policy_arn" { variable "custom_policy" { description = <<-EOF - A custom lambda policy. Multi-statement is supported. + A custom IAM policy. Multi-statement is supported. Basic example: ``` statement1 = { diff --git a/modules/iam/versions.tf b/modules/iam/versions.tf index 9ddb384..3bd8c04 100644 --- a/modules/iam/versions.tf +++ b/modules/iam/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.0.0, < 2.0.0" + required_version = ">= 1.5.0, < 2.0.0" required_providers { aws = { source = "hashicorp/aws" From 5bc718e8d01f1c6b1506a093e200f8f831e2c987 Mon Sep 17 00:00:00 2001 From: Lukasz Stadnik Date: Wed, 18 Dec 2024 16:48:11 +0100 Subject: [PATCH 13/13] feat(examples): refactor iam --- examples/centralized_design/README.md | 4 +-- examples/centralized_design/main.tf | 22 ++++++++++----- examples/centralized_design/variables.tf | 27 +++++++++++++++++-- examples/centralized_design/versions.tf | 2 +- .../centralized_design_autoscale/README.md | 4 +-- examples/centralized_design_autoscale/main.tf | 19 ++++++++----- .../centralized_design_autoscale/variables.tf | 26 +++++++++++++++++- .../centralized_design_autoscale/versions.tf | 2 +- examples/cloudngfw_combined_design/README.md | 4 +-- examples/cloudngfw_combined_design/main.tf | 21 ++++++++++----- .../cloudngfw_combined_design/variables.tf | 27 +++++++++++++++++-- .../cloudngfw_combined_design/versions.tf | 2 +- examples/cloudngfw_isolated_design/README.md | 4 +-- examples/cloudngfw_isolated_design/main.tf | 21 ++++++++++----- .../cloudngfw_isolated_design/variables.tf | 27 +++++++++++++++++-- .../cloudngfw_isolated_design/versions.tf | 2 +- examples/combined_design/README.md | 4 +-- examples/combined_design/main.tf | 22 ++++++++++----- examples/combined_design/variables.tf | 27 +++++++++++++++++-- examples/combined_design/versions.tf | 2 +- examples/combined_design_autoscale/README.md | 4 +-- examples/combined_design_autoscale/main.tf | 19 ++++++++----- .../combined_design_autoscale/variables.tf | 26 +++++++++++++++++- .../combined_design_autoscale/versions.tf | 2 +- examples/isolated_design/README.md | 4 +-- examples/isolated_design/main.tf | 22 ++++++++++----- examples/isolated_design/variables.tf | 27 +++++++++++++++++-- examples/isolated_design/versions.tf | 2 +- examples/isolated_design_autoscale/README.md | 4 +-- examples/isolated_design_autoscale/main.tf | 19 ++++++++----- .../isolated_design_autoscale/variables.tf | 26 +++++++++++++++++- .../isolated_design_autoscale/versions.tf | 2 +- examples/panorama_standalone/README.md | 4 +-- examples/panorama_standalone/main.tf | 21 ++++++++++----- examples/panorama_standalone/variables.tf | 27 +++++++++++++++++-- examples/panorama_standalone/versions.tf | 2 +- examples/vmseries_standalone/README.md | 4 +-- examples/vmseries_standalone/main.tf | 23 ++++++++++------ examples/vmseries_standalone/variables.tf | 27 +++++++++++++++++-- examples/vmseries_standalone/versions.tf | 2 +- modules/iam/README.md | 4 +-- 41 files changed, 423 insertions(+), 117 deletions(-) diff --git a/examples/centralized_design/README.md b/examples/centralized_design/README.md index 77501b7..e6538e9 100644 --- a/examples/centralized_design/README.md +++ b/examples/centralized_design/README.md @@ -58,7 +58,7 @@ To enable access from the session manager, the Internet connection for a public | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | | [local](#requirement\_local) | ~> 2.4.0 | @@ -103,7 +103,7 @@ To enable access from the session manager, the Internet connection for a public |------|-------------|------|---------|:--------:| | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `gwlb`: key of GWLB
- `vpc`: key of VPC
- `subnet_group`: key of the subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
gwlb = "security_gwlb"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
}
}
|
map(object({
name = string
gwlb = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
}))
| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.

Following properties are available:
- `name`: name of the GWLB
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
gwlbs = {
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | -| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "centralized_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "centralized_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
map(object({
role_name = string
create_role = optional(bool, true)
principal_role = optional(string, "ec2.amazonaws.com")
create_instance_profile = optional(bool, false)
instance_profile_name = optional(string)
create_lambda_policy = optional(bool, false)
create_bootrap_policy = optional(bool, false)
policy_arn = optional(string)
create_vmseries_policy = optional(bool, false)
create_panorama_policy = optional(bool, false)
custom_policy = optional(map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
})))
delicense_ssm_param_name = optional(string)
aws_s3_bucket = optional(string)
}))
|
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "centralized_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "centralized_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [natgws](#input\_natgws) | A map defining NAT Gateways.

Following properties are available:
- `name`: name of NAT Gateway
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
natgws = {
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | | [panorama\_attachment](#input\_panorama\_attachment) | A object defining TGW attachment and CIDR for Panorama.

Following properties are available:
- `transit_gateway_attachment_id`: ID of attachment for Panorama
- `vpc_cidr`: CIDR of the VPC, where Panorama is deployed

Example:
panorama = {
transit_gateway_attachment_id = "tgw-attach-123456789"
vpc_cidr = "10.255.0.0/24"
}
|
object({
transit_gateway_attachment_id = string
vpc_cidr = string
})
| `null` | no | diff --git a/examples/centralized_design/main.tf b/examples/centralized_design/main.tf index 1bfb5c6..b951a6c 100644 --- a/examples/centralized_design/main.tf +++ b/examples/centralized_design/main.tf @@ -235,13 +235,21 @@ module "iam" { for_each = var.iam_policies - name_prefix = var.name_prefix - tags = var.tags - role_name = each.value.role_name - create_instance_profile = try(each.value.create_instance_profile, false) - instance_profile_name = try(each.value.instance_profile_name, null) - policy_arn = try(each.value.policy_arn, null) - create_vmseries_policy = try(each.value.create_vmseries_policy, false) + name_prefix = var.name_prefix + tags = var.tags + role_name = each.value.role_name + create_role = each.value.create_role + principal_role = each.value.principal_role + create_instance_profile = each.value.create_instance_profile + instance_profile_name = each.value.instance_profile_name + create_lambda_policy = each.value.create_lambda_policy + create_bootrap_policy = each.value.create_bootrap_policy + policy_arn = each.value.policy_arn + create_vmseries_policy = each.value.create_vmseries_policy + create_panorama_policy = each.value.create_panorama_policy + custom_policy = each.value.custom_policy + delicense_ssm_param_name = each.value.delicense_ssm_param_name + aws_s3_bucket = each.value.aws_s3_bucket } ### SPOKE VM INSTANCES #### diff --git a/examples/centralized_design/variables.tf b/examples/centralized_design/variables.tf index e98e378..8159acd 100644 --- a/examples/centralized_design/variables.tf +++ b/examples/centralized_design/variables.tf @@ -18,8 +18,6 @@ variable "ssh_key_name" { ### IAM variable "iam_policies" { description = "A map defining an IAM policies, roles etc." - type = any - default = { spoke = { create_instance_profile = true @@ -34,6 +32,31 @@ variable "iam_policies" { create_vmseries_policy = true } } + type = map(object({ + role_name = string + create_role = optional(bool, true) + principal_role = optional(string, "ec2.amazonaws.com") + create_instance_profile = optional(bool, false) + instance_profile_name = optional(string) + create_lambda_policy = optional(bool, false) + create_bootrap_policy = optional(bool, false) + policy_arn = optional(string) + create_vmseries_policy = optional(bool, false) + create_panorama_policy = optional(bool, false) + custom_policy = optional(map(object({ + sid = string + effect = string + actions = list(string) + resources = list(string) + condition = optional(object({ + test = string + variable = string + values = list(string) + })) + }))) + delicense_ssm_param_name = optional(string) + aws_s3_bucket = optional(string) + })) } ### VPC diff --git a/examples/centralized_design/versions.tf b/examples/centralized_design/versions.tf index 397101e..a55d376 100644 --- a/examples/centralized_design/versions.tf +++ b/examples/centralized_design/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.0, < 2.0.0" + required_version = ">= 1.5.0, < 2.0.0" required_providers { aws = { source = "hashicorp/aws" diff --git a/examples/centralized_design_autoscale/README.md b/examples/centralized_design_autoscale/README.md index 76393b5..452ff99 100644 --- a/examples/centralized_design_autoscale/README.md +++ b/examples/centralized_design_autoscale/README.md @@ -140,7 +140,7 @@ statistic = "Maximum" | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | | [local](#requirement\_local) | ~> 2.4.0 | @@ -184,7 +184,7 @@ statistic = "Maximum" |------|-------------|------|---------|:--------:| | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `gwlb`: key of GWLB
- `vpc`: key of VPC
- `subnet_group`: key of the subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
gwlb = "security_gwlb"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
}
}
|
map(object({
name = string
gwlb = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
}))
| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.

Following properties are available:
- `name`: name of the GWLB
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
gwlbs = {
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | -| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"lambda": {
"create_lambda_policy": true,
"delicense_ssm_param_name": "secret_name",
"principal_role": "lambda.amazonaws.com",
"role_name": "lambda_role"
},
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "centralized_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "centralized_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
map(object({
role_name = string
create_role = optional(bool, true)
principal_role = optional(string, "ec2.amazonaws.com")
create_instance_profile = optional(bool, false)
instance_profile_name = optional(string)
create_lambda_policy = optional(bool, false)
create_bootrap_policy = optional(bool, false)
policy_arn = optional(string)
create_vmseries_policy = optional(bool, false)
create_panorama_policy = optional(bool, false)
custom_policy = optional(map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
})))
delicense_ssm_param_name = optional(string)
aws_s3_bucket = optional(string)
}))
|
{
"lambda": {
"create_lambda_policy": true,
"delicense_ssm_param_name": "secret_name",
"principal_role": "lambda.amazonaws.com",
"role_name": "lambda_role"
},
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "centralized_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "centralized_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [natgws](#input\_natgws) | A map defining NAT Gateways.

Following properties are available:
- `name`: name of NAT Gateway
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
natgws = {
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | | [panorama\_attachment](#input\_panorama\_attachment) | A object defining TGW attachment and CIDR for Panorama.

Following properties are available:
- `transit_gateway_attachment_id`: ID of attachment for Panorama
- `vpc_cidr`: CIDR of the VPC, where Panorama is deployed

Example:
panorama = {
transit_gateway_attachment_id = "tgw-attach-123456789"
vpc_cidr = "10.255.0.0/24"
}
|
object({
transit_gateway_attachment_id = string
vpc_cidr = string
})
| `null` | no | diff --git a/examples/centralized_design_autoscale/main.tf b/examples/centralized_design_autoscale/main.tf index 992de85..26827d2 100644 --- a/examples/centralized_design_autoscale/main.tf +++ b/examples/centralized_design_autoscale/main.tf @@ -244,13 +244,18 @@ module "iam" { name_prefix = var.name_prefix tags = var.tags role_name = each.value.role_name - create_instance_profile = try(each.value.create_instance_profile, false) - instance_profile_name = try(each.value.instance_profile_name, null) - policy_arn = try(each.value.policy_arn, null) - create_vmseries_policy = try(each.value.create_vmseries_policy, false) - create_lambda_policy = try(each.value.create_lambda_policy, false) - delicense_ssm_param_name = try(each.value.delicense_ssm_param_name, null) - principal_role = try(each.value.principal_role, "ec2.amazonaws.com") + create_role = each.value.create_role + principal_role = each.value.principal_role + create_instance_profile = each.value.create_instance_profile + instance_profile_name = each.value.instance_profile_name + create_lambda_policy = each.value.create_lambda_policy + create_bootrap_policy = each.value.create_bootrap_policy + policy_arn = each.value.policy_arn + create_vmseries_policy = each.value.create_vmseries_policy + create_panorama_policy = each.value.create_panorama_policy + custom_policy = each.value.custom_policy + delicense_ssm_param_name = each.value.delicense_ssm_param_name + aws_s3_bucket = each.value.aws_s3_bucket } ### SPOKE VM INSTANCES #### diff --git a/examples/centralized_design_autoscale/variables.tf b/examples/centralized_design_autoscale/variables.tf index 6ce8682..5bbef27 100644 --- a/examples/centralized_design_autoscale/variables.tf +++ b/examples/centralized_design_autoscale/variables.tf @@ -18,7 +18,6 @@ variable "ssh_key_name" { ###IAM variable "iam_policies" { description = "A map defining an IAM policies, roles etc." - type = any default = { spoke = { create_instance_profile = true @@ -39,6 +38,31 @@ variable "iam_policies" { create_lambda_policy = true } } + type = map(object({ + role_name = string + create_role = optional(bool, true) + principal_role = optional(string, "ec2.amazonaws.com") + create_instance_profile = optional(bool, false) + instance_profile_name = optional(string) + create_lambda_policy = optional(bool, false) + create_bootrap_policy = optional(bool, false) + policy_arn = optional(string) + create_vmseries_policy = optional(bool, false) + create_panorama_policy = optional(bool, false) + custom_policy = optional(map(object({ + sid = string + effect = string + actions = list(string) + resources = list(string) + condition = optional(object({ + test = string + variable = string + values = list(string) + })) + }))) + delicense_ssm_param_name = optional(string) + aws_s3_bucket = optional(string) + })) } ### VPC diff --git a/examples/centralized_design_autoscale/versions.tf b/examples/centralized_design_autoscale/versions.tf index 397101e..a55d376 100644 --- a/examples/centralized_design_autoscale/versions.tf +++ b/examples/centralized_design_autoscale/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.0, < 2.0.0" + required_version = ">= 1.5.0, < 2.0.0" required_providers { aws = { source = "hashicorp/aws" diff --git a/examples/cloudngfw_combined_design/README.md b/examples/cloudngfw_combined_design/README.md index 716a1b4..4b2c968 100644 --- a/examples/cloudngfw_combined_design/README.md +++ b/examples/cloudngfw_combined_design/README.md @@ -84,7 +84,7 @@ To enable access from the session manager, the Internet connection for a public | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | | [cloudngfwaws](#requirement\_cloudngfwaws) | 2.0.6 | | [time](#requirement\_time) | 0.11.1 | @@ -127,7 +127,7 @@ To enable access from the session manager, the Internet connection for a public |------|-------------|------|---------|:--------:| | [cloudngfws](#input\_cloudngfws) | A map defining Cloud NGFWs.

Following properties are available:
- `name` : name of CloudNGFW
- `vpc` : key of the VPC
- `subnet_group` : group of subnets
- `description` : Use for internal purposes.
- `security_rules`: Security Rules definition.
- `log_profiles` : Log Profile definition.

Example:
cloudngfws = {
cloudngfws_security = {
name = "cloudngfw01"
vpc = "app_vpc"
subnet_group = "app_gwlbe"
description = "description"
security_rules =
{
rule_1 = {
rule_list = "LocalRule"
priority = 3
name = "tf-security-rule"
description = "Also configured by Terraform"
source_cidrs = ["any"]
destination_cidrs = ["0.0.0.0/0"]
negate_destination = false
protocol = "application-default"
applications = ["any"]
category_feeds = null
category_url_category_names = null
action = "Allow"
logging = true
audit_comment = "initial config"
}
}
log_profiles = {
dest_1 = {
create_cw = true
name = "PaloAltoCloudNGFW"
destination_type = "CloudWatchLogs"
log_type = "THREAT"
}
dest_2 = {
create_cw = true
name = "PaloAltoCloudNGFW"
destination_type = "CloudWatchLogs"
log_type = "TRAFFIC"
}
dest_3 = {
create_cw = true
name = "PaloAltoCloudNGFW"
destination_type = "CloudWatchLogs"
log_type = "DECRYPTION"
}
}
profile_config = {
anti_spyware = "BestPractice"
anti_virus = "BestPractice"
vulnerability = "BestPractice"
file_blocking = "BestPractice"
url_filtering = "BestPractice"
}
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
description = string
security_rules = map(any)
log_profiles = map(any)
profile_config = map(any)
}))
| `{}` | no | | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `vpc`: key of VPC
- `subnet_group`: key of the subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint
- `delay`: delay in seconds for the endpoint
- `cloudngfw`: key of the Cloud NGFW

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
delay = 60
cloudngfw = "cloudngfw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
delay = number
cloudngfw = string
}))
| `{}` | no | -| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "combined_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
}
}
| no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
map(object({
role_name = string
create_role = optional(bool, true)
principal_role = optional(string, "ec2.amazonaws.com")
create_instance_profile = optional(bool, false)
instance_profile_name = optional(string)
create_lambda_policy = optional(bool, false)
create_bootrap_policy = optional(bool, false)
policy_arn = optional(string)
create_vmseries_policy = optional(bool, false)
create_panorama_policy = optional(bool, false)
custom_policy = optional(map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
})))
delicense_ssm_param_name = optional(string)
aws_s3_bucket = optional(string)
}))
|
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "combined_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [natgws](#input\_natgws) | A map defining NAT Gateways.

Following properties are available:
- `name`: name of NAT Gateway
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
natgws = {
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | | [provider\_account](#input\_provider\_account) | The AWS Account where the resources should be deployed. | `string` | n/a | yes | diff --git a/examples/cloudngfw_combined_design/main.tf b/examples/cloudngfw_combined_design/main.tf index d6d5ce5..55e7a1a 100644 --- a/examples/cloudngfw_combined_design/main.tf +++ b/examples/cloudngfw_combined_design/main.tf @@ -135,12 +135,21 @@ module "iam" { for_each = var.iam_policies - name_prefix = var.name_prefix - tags = var.tags - role_name = each.value.role_name - create_instance_profile = try(each.value.create_instance_profile, false) - instance_profile_name = try(each.value.instance_profile_name, null) - policy_arn = try(each.value.policy_arn, null) + name_prefix = var.name_prefix + tags = var.tags + role_name = each.value.role_name + create_role = each.value.create_role + principal_role = each.value.principal_role + create_instance_profile = each.value.create_instance_profile + instance_profile_name = each.value.instance_profile_name + create_lambda_policy = each.value.create_lambda_policy + create_bootrap_policy = each.value.create_bootrap_policy + policy_arn = each.value.policy_arn + create_vmseries_policy = each.value.create_vmseries_policy + create_panorama_policy = each.value.create_panorama_policy + custom_policy = each.value.custom_policy + delicense_ssm_param_name = each.value.delicense_ssm_param_name + aws_s3_bucket = each.value.aws_s3_bucket } ### SPOKE VM INSTANCES #### diff --git a/examples/cloudngfw_combined_design/variables.tf b/examples/cloudngfw_combined_design/variables.tf index dd13d1d..ce151a2 100644 --- a/examples/cloudngfw_combined_design/variables.tf +++ b/examples/cloudngfw_combined_design/variables.tf @@ -28,8 +28,6 @@ variable "ssh_key_name" { ### IAM variable "iam_policies" { description = "A map defining an IAM policies, roles etc." - type = any - default = { spoke = { create_instance_profile = true @@ -38,6 +36,31 @@ variable "iam_policies" { policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" } } + type = map(object({ + role_name = string + create_role = optional(bool, true) + principal_role = optional(string, "ec2.amazonaws.com") + create_instance_profile = optional(bool, false) + instance_profile_name = optional(string) + create_lambda_policy = optional(bool, false) + create_bootrap_policy = optional(bool, false) + policy_arn = optional(string) + create_vmseries_policy = optional(bool, false) + create_panorama_policy = optional(bool, false) + custom_policy = optional(map(object({ + sid = string + effect = string + actions = list(string) + resources = list(string) + condition = optional(object({ + test = string + variable = string + values = list(string) + })) + }))) + delicense_ssm_param_name = optional(string) + aws_s3_bucket = optional(string) + })) } ### VPC diff --git a/examples/cloudngfw_combined_design/versions.tf b/examples/cloudngfw_combined_design/versions.tf index ff4c6a8..1854a5d 100644 --- a/examples/cloudngfw_combined_design/versions.tf +++ b/examples/cloudngfw_combined_design/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.0, < 2.0.0" + required_version = ">= 1.5.0, < 2.0.0" required_providers { aws = { source = "hashicorp/aws" diff --git a/examples/cloudngfw_isolated_design/README.md b/examples/cloudngfw_isolated_design/README.md index e9a463b..858ad5b 100644 --- a/examples/cloudngfw_isolated_design/README.md +++ b/examples/cloudngfw_isolated_design/README.md @@ -83,7 +83,7 @@ To enable access from the session manager, the Internet connection for a public | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | | [cloudngfwaws](#requirement\_cloudngfwaws) | 2.0.6 | | [time](#requirement\_time) | 0.11.1 | @@ -123,7 +123,7 @@ To enable access from the session manager, the Internet connection for a public |------|-------------|------|---------|:--------:| | [cloudngfws](#input\_cloudngfws) | A map defining Cloud NGFWs.

Following properties are available:
- `name` : name of CloudNGFW
- `vpc` : key of the VPC
- `subnet_group` : group of subnets
- `description` : Use for internal purposes.
- `security_rules`: Security Rules definition.
- `log_profiles` : Log Profile definition.

Example:
cloudngfws = {
cloudngfws_security = {
name = "cloudngfw01"
vpc = "app_vpc"
subnet_group = "app_gwlbe"
description = "description"
security_rules =
{
rule_1 = {
rule_list = "LocalRule"
priority = 3
name = "tf-security-rule"
description = "Also configured by Terraform"
source_cidrs = ["any"]
destination_cidrs = ["0.0.0.0/0"]
negate_destination = false
protocol = "application-default"
applications = ["any"]
category_feeds = null
category_url_category_names = null
action = "Allow"
logging = true
audit_comment = "initial config"
}
}
log_profiles = {
dest_1 = {
create_cw = true
name = "PaloAltoCloudNGFW"
destination_type = "CloudWatchLogs"
log_type = "THREAT"
}
dest_2 = {
create_cw = true
name = "PaloAltoCloudNGFW"
destination_type = "CloudWatchLogs"
log_type = "TRAFFIC"
}
dest_3 = {
create_cw = true
name = "PaloAltoCloudNGFW"
destination_type = "CloudWatchLogs"
log_type = "DECRYPTION"
}
}
profile_config = {
anti_spyware = "BestPractice"
anti_virus = "BestPractice"
vulnerability = "BestPractice"
file_blocking = "BestPractice"
url_filtering = "BestPractice"
}
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
description = string
security_rules = map(any)
log_profiles = map(any)
profile_config = map(any)
}))
| `{}` | no | | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `vpc`: key of VPC
- `subnet_group`: key of the subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint
- `to_vpc`: VPC to which traffic from GWLB endpoint is routed to
- `to_subnet_group`: subnet\_group to which traffic from GWLB endpoint is routed to
- `delay`: delay in seconds for the endpoint
- `cloudngfw`: key of the Cloud NGFW

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
delay = 60
cloudngfw = "cloudngfw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
to_vpc = optional(string)
to_subnet_group = optional(string)
delay = number
cloudngfw = string
}))
| `{}` | no | -| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "isolated_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
}
}
| no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
map(object({
role_name = string
create_role = optional(bool, true)
principal_role = optional(string, "ec2.amazonaws.com")
create_instance_profile = optional(bool, false)
instance_profile_name = optional(string)
create_lambda_policy = optional(bool, false)
create_bootrap_policy = optional(bool, false)
policy_arn = optional(string)
create_vmseries_policy = optional(bool, false)
create_panorama_policy = optional(bool, false)
custom_policy = optional(map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
})))
delicense_ssm_param_name = optional(string)
aws_s3_bucket = optional(string)
}))
|
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "isolated_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [natgws](#input\_natgws) | A map defining NAT Gateways.

Following properties are available:
- `name`: name of NAT Gateway
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
natgws = {
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | | [provider\_account](#input\_provider\_account) | The AWS Account where the resources should be deployed. | `string` | n/a | yes | diff --git a/examples/cloudngfw_isolated_design/main.tf b/examples/cloudngfw_isolated_design/main.tf index 53649ca..e1b68a2 100644 --- a/examples/cloudngfw_isolated_design/main.tf +++ b/examples/cloudngfw_isolated_design/main.tf @@ -99,12 +99,21 @@ module "iam" { for_each = var.iam_policies - name_prefix = var.name_prefix - tags = var.tags - role_name = each.value.role_name - create_instance_profile = try(each.value.create_instance_profile, false) - instance_profile_name = try(each.value.instance_profile_name, null) - policy_arn = try(each.value.policy_arn, null) + name_prefix = var.name_prefix + tags = var.tags + role_name = each.value.role_name + create_role = each.value.create_role + principal_role = each.value.principal_role + create_instance_profile = each.value.create_instance_profile + instance_profile_name = each.value.instance_profile_name + create_lambda_policy = each.value.create_lambda_policy + create_bootrap_policy = each.value.create_bootrap_policy + policy_arn = each.value.policy_arn + create_vmseries_policy = each.value.create_vmseries_policy + create_panorama_policy = each.value.create_panorama_policy + custom_policy = each.value.custom_policy + delicense_ssm_param_name = each.value.delicense_ssm_param_name + aws_s3_bucket = each.value.aws_s3_bucket } ### SPOKE VM INSTANCES #### diff --git a/examples/cloudngfw_isolated_design/variables.tf b/examples/cloudngfw_isolated_design/variables.tf index d9ba4ad..15a6fea 100644 --- a/examples/cloudngfw_isolated_design/variables.tf +++ b/examples/cloudngfw_isolated_design/variables.tf @@ -28,8 +28,6 @@ variable "ssh_key_name" { ### IAM variable "iam_policies" { description = "A map defining an IAM policies, roles etc." - type = any - default = { spoke = { create_instance_profile = true @@ -38,6 +36,31 @@ variable "iam_policies" { policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" } } + type = map(object({ + role_name = string + create_role = optional(bool, true) + principal_role = optional(string, "ec2.amazonaws.com") + create_instance_profile = optional(bool, false) + instance_profile_name = optional(string) + create_lambda_policy = optional(bool, false) + create_bootrap_policy = optional(bool, false) + policy_arn = optional(string) + create_vmseries_policy = optional(bool, false) + create_panorama_policy = optional(bool, false) + custom_policy = optional(map(object({ + sid = string + effect = string + actions = list(string) + resources = list(string) + condition = optional(object({ + test = string + variable = string + values = list(string) + })) + }))) + delicense_ssm_param_name = optional(string) + aws_s3_bucket = optional(string) + })) } ### VPC diff --git a/examples/cloudngfw_isolated_design/versions.tf b/examples/cloudngfw_isolated_design/versions.tf index 609cafb..2b9f216 100644 --- a/examples/cloudngfw_isolated_design/versions.tf +++ b/examples/cloudngfw_isolated_design/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.0, < 2.0.0" + required_version = ">= 1.5.0, < 2.0.0" required_providers { aws = { source = "hashicorp/aws" diff --git a/examples/combined_design/README.md b/examples/combined_design/README.md index 49bda47..14cdf1f 100644 --- a/examples/combined_design/README.md +++ b/examples/combined_design/README.md @@ -94,7 +94,7 @@ If no errors occurred during deployment, configure the VM-Series machines as exp | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | ### Providers @@ -137,7 +137,7 @@ If no errors occurred during deployment, configure the VM-Series machines as exp |------|-------------|------|---------|:--------:| | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `gwlb`: key of GWLB
- `vpc`: key of VPC
- `subnet_group`: key of the subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
gwlb = "security_gwlb"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
}
}
|
map(object({
name = string
gwlb = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
}))
| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.

Following properties are available:
- `name`: name of the GWLB
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
gwlbs = {
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | -| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "combined_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "combined_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
map(object({
role_name = string
create_role = optional(bool, true)
principal_role = optional(string, "ec2.amazonaws.com")
create_instance_profile = optional(bool, false)
instance_profile_name = optional(string)
create_lambda_policy = optional(bool, false)
create_bootrap_policy = optional(bool, false)
policy_arn = optional(string)
create_vmseries_policy = optional(bool, false)
create_panorama_policy = optional(bool, false)
custom_policy = optional(map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
})))
delicense_ssm_param_name = optional(string)
aws_s3_bucket = optional(string)
}))
|
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "combined_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "combined_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [natgws](#input\_natgws) | A map defining NAT Gateways.

Following properties are available:
- `name`: name of NAT Gateway
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
natgws = {
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | | [panorama\_attachment](#input\_panorama\_attachment) | An object defining TGW attachment and CIDR for Panorama.


Following properties are available:
- `transit_gateway_attachment_id`: ID of attachment for Panorama
- `vpc_cidr`: CIDR of the VPC, where Panorama is deployed

Example:
panorama = {
transit_gateway_attachment_id = "tgw-attach-123456789"
vpc_cidr = "10.255.0.0/24"
}
|
object({
transit_gateway_attachment_id = string
vpc_cidr = string
})
| `null` | no | diff --git a/examples/combined_design/main.tf b/examples/combined_design/main.tf index 41f5046..cc2d24d 100644 --- a/examples/combined_design/main.tf +++ b/examples/combined_design/main.tf @@ -165,13 +165,21 @@ module "iam" { for_each = var.iam_policies - name_prefix = var.name_prefix - tags = var.tags - role_name = each.value.role_name - create_instance_profile = try(each.value.create_instance_profile, false) - instance_profile_name = try(each.value.instance_profile_name, null) - policy_arn = try(each.value.policy_arn, null) - create_vmseries_policy = try(each.value.create_vmseries_policy, false) + name_prefix = var.name_prefix + tags = var.tags + role_name = each.value.role_name + create_role = each.value.create_role + principal_role = each.value.principal_role + create_instance_profile = each.value.create_instance_profile + instance_profile_name = each.value.instance_profile_name + create_lambda_policy = each.value.create_lambda_policy + create_bootrap_policy = each.value.create_bootrap_policy + policy_arn = each.value.policy_arn + create_vmseries_policy = each.value.create_vmseries_policy + create_panorama_policy = each.value.create_panorama_policy + custom_policy = each.value.custom_policy + delicense_ssm_param_name = each.value.delicense_ssm_param_name + aws_s3_bucket = each.value.aws_s3_bucket } ### VM-Series INSTANCES diff --git a/examples/combined_design/variables.tf b/examples/combined_design/variables.tf index 4ec074a..1c34635 100644 --- a/examples/combined_design/variables.tf +++ b/examples/combined_design/variables.tf @@ -18,8 +18,6 @@ variable "ssh_key_name" { ### IAM variable "iam_policies" { description = "A map defining an IAM policies, roles etc." - type = any - default = { spoke = { create_instance_profile = true @@ -34,6 +32,31 @@ variable "iam_policies" { create_vmseries_policy = true } } + type = map(object({ + role_name = string + create_role = optional(bool, true) + principal_role = optional(string, "ec2.amazonaws.com") + create_instance_profile = optional(bool, false) + instance_profile_name = optional(string) + create_lambda_policy = optional(bool, false) + create_bootrap_policy = optional(bool, false) + policy_arn = optional(string) + create_vmseries_policy = optional(bool, false) + create_panorama_policy = optional(bool, false) + custom_policy = optional(map(object({ + sid = string + effect = string + actions = list(string) + resources = list(string) + condition = optional(object({ + test = string + variable = string + values = list(string) + })) + }))) + delicense_ssm_param_name = optional(string) + aws_s3_bucket = optional(string) + })) } ### VPC diff --git a/examples/combined_design/versions.tf b/examples/combined_design/versions.tf index 6455660..afd605b 100644 --- a/examples/combined_design/versions.tf +++ b/examples/combined_design/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.0, < 2.0.0" + required_version = ">= 1.5.0, < 2.0.0" required_providers { aws = { source = "hashicorp/aws" diff --git a/examples/combined_design_autoscale/README.md b/examples/combined_design_autoscale/README.md index ce9fcf9..49e7f3a 100644 --- a/examples/combined_design_autoscale/README.md +++ b/examples/combined_design_autoscale/README.md @@ -215,7 +215,7 @@ To enable access from the session manager, the Internet connection for a public | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | ### Providers @@ -256,7 +256,7 @@ To enable access from the session manager, the Internet connection for a public |------|-------------|------|---------|:--------:| | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `gwlb`: key of GWLB
- `vpc`: key of VPC
- `subnet_group`: key of subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
gwlb = "security_gwlb"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
}
}
|
map(object({
name = string
gwlb = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
}))
| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.

Following properties are available:
- `name`: name of the GWLB
- `vpc`: VPC key
- `subnet_group`: subnet\_group key

Example:
gwlbs = {
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | -| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"lambda": {
"create_lambda_policy": true,
"delicense_ssm_param_name": "secret_name",
"principal_role": "lambda.amazonaws.com",
"role_name": "lambda_role"
},
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "combined_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "combined_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
map(object({
role_name = string
create_role = optional(bool, true)
principal_role = optional(string, "ec2.amazonaws.com")
create_instance_profile = optional(bool, false)
instance_profile_name = optional(string)
create_lambda_policy = optional(bool, false)
create_bootrap_policy = optional(bool, false)
policy_arn = optional(string)
create_vmseries_policy = optional(bool, false)
create_panorama_policy = optional(bool, false)
custom_policy = optional(map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
})))
delicense_ssm_param_name = optional(string)
aws_s3_bucket = optional(string)
}))
|
{
"lambda": {
"create_lambda_policy": true,
"delicense_ssm_param_name": "secret_name",
"principal_role": "lambda.amazonaws.com",
"role_name": "lambda_role"
},
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "combined_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "combined_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [natgws](#input\_natgws) | A map defining NAT Gateways.

Following properties are available:
- `name`: name of NAT Gateway
- `vpc`: VPC key
- `subnet_group`: subnet\_group key

Example:
natgws = {
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | | [panorama\_attachment](#input\_panorama\_attachment) | A object defining TGW attachment and CIDR for Panorama.

Following properties are available:
- `transit_gateway_attachment_id`: ID of attachment for Panorama
- `vpc_cidr`: CIDR of the VPC, where Panorama is deployed

Example:
panorama = {
transit_gateway_attachment_id = "tgw-attach-123456789"
vpc_cidr = "10.255.0.0/24"
}
|
object({
transit_gateway_attachment_id = string
vpc_cidr = string
})
| `null` | no | diff --git a/examples/combined_design_autoscale/main.tf b/examples/combined_design_autoscale/main.tf index 03ffc9f..7444f1e 100644 --- a/examples/combined_design_autoscale/main.tf +++ b/examples/combined_design_autoscale/main.tf @@ -204,13 +204,18 @@ module "iam" { name_prefix = var.name_prefix tags = var.tags role_name = each.value.role_name - create_instance_profile = try(each.value.create_instance_profile, false) - instance_profile_name = try(each.value.instance_profile_name, null) - policy_arn = try(each.value.policy_arn, null) - create_vmseries_policy = try(each.value.create_vmseries_policy, false) - create_lambda_policy = try(each.value.create_lambda_policy, false) - delicense_ssm_param_name = try(each.value.delicense_ssm_param_name, null) - principal_role = try(each.value.principal_role, "ec2.amazonaws.com") + create_role = each.value.create_role + principal_role = each.value.principal_role + create_instance_profile = each.value.create_instance_profile + instance_profile_name = each.value.instance_profile_name + create_lambda_policy = each.value.create_lambda_policy + create_bootrap_policy = each.value.create_bootrap_policy + policy_arn = each.value.policy_arn + create_vmseries_policy = each.value.create_vmseries_policy + create_panorama_policy = each.value.create_panorama_policy + custom_policy = each.value.custom_policy + delicense_ssm_param_name = each.value.delicense_ssm_param_name + aws_s3_bucket = each.value.aws_s3_bucket } ### SPOKE VM INSTANCES #### diff --git a/examples/combined_design_autoscale/variables.tf b/examples/combined_design_autoscale/variables.tf index dbb2b22..26e4ce7 100644 --- a/examples/combined_design_autoscale/variables.tf +++ b/examples/combined_design_autoscale/variables.tf @@ -18,7 +18,6 @@ variable "ssh_key_name" { ###IAM variable "iam_policies" { description = "A map defining an IAM policies, roles etc." - type = any default = { spoke = { create_instance_profile = true @@ -39,6 +38,31 @@ variable "iam_policies" { create_lambda_policy = true } } + type = map(object({ + role_name = string + create_role = optional(bool, true) + principal_role = optional(string, "ec2.amazonaws.com") + create_instance_profile = optional(bool, false) + instance_profile_name = optional(string) + create_lambda_policy = optional(bool, false) + create_bootrap_policy = optional(bool, false) + policy_arn = optional(string) + create_vmseries_policy = optional(bool, false) + create_panorama_policy = optional(bool, false) + custom_policy = optional(map(object({ + sid = string + effect = string + actions = list(string) + resources = list(string) + condition = optional(object({ + test = string + variable = string + values = list(string) + })) + }))) + delicense_ssm_param_name = optional(string) + aws_s3_bucket = optional(string) + })) } ### VPC diff --git a/examples/combined_design_autoscale/versions.tf b/examples/combined_design_autoscale/versions.tf index 6455660..afd605b 100644 --- a/examples/combined_design_autoscale/versions.tf +++ b/examples/combined_design_autoscale/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.0, < 2.0.0" + required_version = ">= 1.5.0, < 2.0.0" required_providers { aws = { source = "hashicorp/aws" diff --git a/examples/isolated_design/README.md b/examples/isolated_design/README.md index 5022e11..c581ba4 100644 --- a/examples/isolated_design/README.md +++ b/examples/isolated_design/README.md @@ -65,7 +65,7 @@ To enable access from the session manager, the Internet connection for a public | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | ### Providers @@ -104,7 +104,7 @@ To enable access from the session manager, the Internet connection for a public |------|-------------|------|---------|:--------:| | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `gwlb`: key of GWLB
- `vpc`: key of VPC
- `subnet_group`: key of subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
gwlb = "security_gwlb"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
}
}
|
map(object({
name = string
gwlb = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
}))
| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.

Following properties are available:
- `name`: name of the GWLB
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
gwlbs = {
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | -| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "isolated_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "isolated_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
map(object({
role_name = string
create_role = optional(bool, true)
principal_role = optional(string, "ec2.amazonaws.com")
create_instance_profile = optional(bool, false)
instance_profile_name = optional(string)
create_lambda_policy = optional(bool, false)
create_bootrap_policy = optional(bool, false)
policy_arn = optional(string)
create_vmseries_policy = optional(bool, false)
create_panorama_policy = optional(bool, false)
custom_policy = optional(map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
})))
delicense_ssm_param_name = optional(string)
aws_s3_bucket = optional(string)
}))
|
{
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "isolated_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "isolated_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [panorama\_connection](#input\_panorama\_connection) | A object defining VPC peering and CIDR for Panorama.

Following properties are available:
- `security_vpc`: key of the security VPC
- `peering_vpc_id`: ID of the VPC for Panorama
- `vpc_cidr`: CIDR of the VPC, where Panorama is deployed

Example:
panorama = {
security_vpc = "security_vpc"
peering_vpc_id = "vpc-1234567890"
vpc_cidr = "10.255.0.0/24"
}
|
object({
security_vpc = string
peering_vpc_id = string
vpc_cidr = string
})
| `null` | no | | [region](#input\_region) | AWS region used to deploy whole infrastructure | `string` | n/a | yes | diff --git a/examples/isolated_design/main.tf b/examples/isolated_design/main.tf index 78f3364..12eb566 100644 --- a/examples/isolated_design/main.tf +++ b/examples/isolated_design/main.tf @@ -154,13 +154,21 @@ module "iam" { for_each = var.iam_policies - name_prefix = var.name_prefix - tags = var.tags - role_name = each.value.role_name - create_instance_profile = try(each.value.create_instance_profile, false) - instance_profile_name = try(each.value.instance_profile_name, null) - policy_arn = try(each.value.policy_arn, null) - create_vmseries_policy = try(each.value.create_vmseries_policy, false) + name_prefix = var.name_prefix + tags = var.tags + role_name = each.value.role_name + create_role = each.value.create_role + principal_role = each.value.principal_role + create_instance_profile = each.value.create_instance_profile + instance_profile_name = each.value.instance_profile_name + create_lambda_policy = each.value.create_lambda_policy + create_bootrap_policy = each.value.create_bootrap_policy + policy_arn = each.value.policy_arn + create_vmseries_policy = each.value.create_vmseries_policy + create_panorama_policy = each.value.create_panorama_policy + custom_policy = each.value.custom_policy + delicense_ssm_param_name = each.value.delicense_ssm_param_name + aws_s3_bucket = each.value.aws_s3_bucket } ### SPOKE VM INSTANCES #### diff --git a/examples/isolated_design/variables.tf b/examples/isolated_design/variables.tf index c711138..b444b03 100644 --- a/examples/isolated_design/variables.tf +++ b/examples/isolated_design/variables.tf @@ -18,8 +18,6 @@ variable "ssh_key_name" { ### IAM variable "iam_policies" { description = "A map defining an IAM policies, roles etc." - type = any - default = { spoke = { create_instance_profile = true @@ -34,6 +32,31 @@ variable "iam_policies" { create_vmseries_policy = true } } + type = map(object({ + role_name = string + create_role = optional(bool, true) + principal_role = optional(string, "ec2.amazonaws.com") + create_instance_profile = optional(bool, false) + instance_profile_name = optional(string) + create_lambda_policy = optional(bool, false) + create_bootrap_policy = optional(bool, false) + policy_arn = optional(string) + create_vmseries_policy = optional(bool, false) + create_panorama_policy = optional(bool, false) + custom_policy = optional(map(object({ + sid = string + effect = string + actions = list(string) + resources = list(string) + condition = optional(object({ + test = string + variable = string + values = list(string) + })) + }))) + delicense_ssm_param_name = optional(string) + aws_s3_bucket = optional(string) + })) } ### VPC diff --git a/examples/isolated_design/versions.tf b/examples/isolated_design/versions.tf index 6455660..afd605b 100644 --- a/examples/isolated_design/versions.tf +++ b/examples/isolated_design/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.0, < 2.0.0" + required_version = ">= 1.5.0, < 2.0.0" required_providers { aws = { source = "hashicorp/aws" diff --git a/examples/isolated_design_autoscale/README.md b/examples/isolated_design_autoscale/README.md index dca5090..519913f 100644 --- a/examples/isolated_design_autoscale/README.md +++ b/examples/isolated_design_autoscale/README.md @@ -173,7 +173,7 @@ statistic = "Maximum" | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | ### Providers @@ -211,7 +211,7 @@ statistic = "Maximum" |------|-------------|------|---------|:--------:| | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.

Following properties are available:
- `name`: name of the GWLB endpoint
- `gwlb`: key of GWLB
- `vpc`: key of VPC
- `subnet_group`: key of the subnet\_group
- `act_as_next_hop`: set to `true` if endpoint is part of an IGW route table e.g. for inbound traffic
- `from_igw_to_vpc`: VPC to which traffic from IGW is routed to the GWLB endpoint
- `from_igw_to_subnet_group` : subnet\_group to which traffic from IGW is routed to the GWLB endpoint

Example:
gwlb_endpoints = {
security_gwlb_eastwest = {
name = "eastwest-gwlb-endpoint"
gwlb = "security_gwlb"
vpc = "security_vpc"
subnet_group = "gwlbe_eastwest"
act_as_next_hop = false
}
}
|
map(object({
name = string
gwlb = string
vpc = string
subnet_group = string
act_as_next_hop = bool
from_igw_to_vpc = optional(string)
from_igw_to_subnet_group = optional(string)
}))
| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.

Following properties are available:
- `name`: name of the GWLB
- `vpc`: key of the VPC
- `subnet_group`: key of the subnet\_group

Example:
gwlbs = {
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
|
map(object({
name = string
vpc = string
subnet_group = string
}))
| `{}` | no | -| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"lambda": {
"create_lambda_policy": true,
"delicense_ssm_param_name": "secret_name",
"principal_role": "lambda.amazonaws.com",
"role_name": "lambda_role"
},
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "isolated_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "isolated_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
map(object({
role_name = string
create_role = optional(bool, true)
principal_role = optional(string, "ec2.amazonaws.com")
create_instance_profile = optional(bool, false)
instance_profile_name = optional(string)
create_lambda_policy = optional(bool, false)
create_bootrap_policy = optional(bool, false)
policy_arn = optional(string)
create_vmseries_policy = optional(bool, false)
create_panorama_policy = optional(bool, false)
custom_policy = optional(map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
})))
delicense_ssm_param_name = optional(string)
aws_s3_bucket = optional(string)
}))
|
{
"lambda": {
"create_lambda_policy": true,
"delicense_ssm_param_name": "secret_name",
"principal_role": "lambda.amazonaws.com",
"role_name": "lambda_role"
},
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "isolated_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
},
"vmseries": {
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "isolated_vmseries_profile",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [panorama\_connection](#input\_panorama\_connection) | A object defining VPC peering and CIDR for Panorama.

Following properties are available:
- `security_vpc`: key of the security VPC
- `peering_vpc_id`: ID of the VPC for Panorama
- `vpc_cidr`: CIDR of the VPC, where Panorama is deployed

Example:
panorama = {
security_vpc = "security_vpc"
peering_vpc_id = "vpc-1234567890"
vpc_cidr = "10.255.0.0/24"
}
|
object({
security_vpc = string
peering_vpc_id = string
vpc_cidr = string
})
| `null` | no | | [region](#input\_region) | AWS region used to deploy whole infrastructure | `string` | n/a | yes | diff --git a/examples/isolated_design_autoscale/main.tf b/examples/isolated_design_autoscale/main.tf index a5dbd70..74251cb 100644 --- a/examples/isolated_design_autoscale/main.tf +++ b/examples/isolated_design_autoscale/main.tf @@ -160,13 +160,18 @@ module "iam" { name_prefix = var.name_prefix tags = var.tags role_name = each.value.role_name - create_instance_profile = try(each.value.create_instance_profile, false) - instance_profile_name = try(each.value.instance_profile_name, null) - policy_arn = try(each.value.policy_arn, null) - create_vmseries_policy = try(each.value.create_vmseries_policy, false) - create_lambda_policy = try(each.value.create_lambda_policy, false) - delicense_ssm_param_name = try(each.value.delicense_ssm_param_name, null) - principal_role = try(each.value.principal_role, "ec2.amazonaws.com") + create_role = each.value.create_role + principal_role = each.value.principal_role + create_instance_profile = each.value.create_instance_profile + instance_profile_name = each.value.instance_profile_name + create_lambda_policy = each.value.create_lambda_policy + create_bootrap_policy = each.value.create_bootrap_policy + policy_arn = each.value.policy_arn + create_vmseries_policy = each.value.create_vmseries_policy + create_panorama_policy = each.value.create_panorama_policy + custom_policy = each.value.custom_policy + delicense_ssm_param_name = each.value.delicense_ssm_param_name + aws_s3_bucket = each.value.aws_s3_bucket } ### SPOKE VM INSTANCES #### diff --git a/examples/isolated_design_autoscale/variables.tf b/examples/isolated_design_autoscale/variables.tf index 5a4cf6c..dd5a7a7 100644 --- a/examples/isolated_design_autoscale/variables.tf +++ b/examples/isolated_design_autoscale/variables.tf @@ -18,7 +18,6 @@ variable "ssh_key_name" { ###IAM variable "iam_policies" { description = "A map defining an IAM policies, roles etc." - type = any default = { spoke = { create_instance_profile = true @@ -39,6 +38,31 @@ variable "iam_policies" { create_lambda_policy = true } } + type = map(object({ + role_name = string + create_role = optional(bool, true) + principal_role = optional(string, "ec2.amazonaws.com") + create_instance_profile = optional(bool, false) + instance_profile_name = optional(string) + create_lambda_policy = optional(bool, false) + create_bootrap_policy = optional(bool, false) + policy_arn = optional(string) + create_vmseries_policy = optional(bool, false) + create_panorama_policy = optional(bool, false) + custom_policy = optional(map(object({ + sid = string + effect = string + actions = list(string) + resources = list(string) + condition = optional(object({ + test = string + variable = string + values = list(string) + })) + }))) + delicense_ssm_param_name = optional(string) + aws_s3_bucket = optional(string) + })) } ### VPC diff --git a/examples/isolated_design_autoscale/versions.tf b/examples/isolated_design_autoscale/versions.tf index 6455660..afd605b 100644 --- a/examples/isolated_design_autoscale/versions.tf +++ b/examples/isolated_design_autoscale/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.0, < 2.0.0" + required_version = ">= 1.5.0, < 2.0.0" required_providers { aws = { source = "hashicorp/aws" diff --git a/examples/panorama_standalone/README.md b/examples/panorama_standalone/README.md index c6df6c2..e620b6c 100644 --- a/examples/panorama_standalone/README.md +++ b/examples/panorama_standalone/README.md @@ -60,7 +60,7 @@ Use a web browser to access https://x.x.x.x and login with admin and your previo | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | ### Providers @@ -84,7 +84,7 @@ No resources. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"panorama": {
"create_instance_profile": true,
"create_panorama_policy": true,
"instance_profile_name": "panorama_profile",
"role_name": "panorama_role"
}
}
| no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
map(object({
role_name = string
create_role = optional(bool, true)
principal_role = optional(string, "ec2.amazonaws.com")
create_instance_profile = optional(bool, false)
instance_profile_name = optional(string)
create_lambda_policy = optional(bool, false)
create_bootrap_policy = optional(bool, false)
policy_arn = optional(string)
create_vmseries_policy = optional(bool, false)
create_panorama_policy = optional(bool, false)
custom_policy = optional(map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
})))
delicense_ssm_param_name = optional(string)
aws_s3_bucket = optional(string)
}))
|
{
"panorama": {
"create_instance_profile": true,
"create_panorama_policy": true,
"instance_profile_name": "panorama_profile",
"role_name": "panorama_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | `""` | no | | [panoramas](#input\_panoramas) | A map defining Panorama instances

Following properties are available:
- `instances`: map of Panorama instances with attributes:
- `az`: name of the Availability Zone
- `private_ip_address`: private IP address for management interface
- `panos_version`: PAN-OS version used for Panorama
- `network`: definition of network settings in object with attributes:
- `vpc`: name of the VPC (needs to be one of the keys in map `vpcs`)
- `subnet_group` - key of the subnet group
- `security_group`: security group assigned to ENI used by Panorama
- `create_public_ip`: true, if public IP address for management should be created
- `ebs`: EBS settings defined in object with attributes:
- `volumes`: list of EBS volumes attached to each instance
- `kms_key_alias`: KMS key alias used for encrypting Panorama EBS
- `iam`: IAM settings in object with attrbiutes:
- `create_role`: enable creation of IAM role
- `role_name`: name of the role to create or use existing one
- `enable_imdsv2`: whether to enable IMDSv2 on the EC2 instance

Example:
{
panorama_ha_pair = {
instances = {
"primary" = {
az = "eu-central-1a"
private_ip_address = "10.255.0.4"
}
"secondary" = {
az = "eu-central-1b"
private_ip_address = "10.255.1.4"
}
}

panos_version = "10.2.3"

network = {
vpc = "management_vpc"
subnet_group = "mgmt"
security_group = "panorama_mgmt"
create_public_ip = true
}

ebs = {
volumes = [
{
name = "ebs-1"
ebs_device_name = "/dev/sdb"
ebs_size = "2000"
ebs_encrypted = true
},
{
name = "ebs-2"
ebs_device_name = "/dev/sdc"
ebs_size = "2000"
ebs_encrypted = true
}
]
kms_key_alias = "aws/ebs"
}

iam = {
create_role = true
role_name = "panorama"
}

enable_imdsv2 = false
}
}
|
map(object({
instances = map(object({
az = string
private_ip_address = string
}))

panos_version = string

network = object({
vpc = string
subnet_group = string
security_group = string
create_public_ip = bool
})

ebs = object({
volumes = list(object({
name = string
ebs_device_name = string
ebs_size = string
}))
encrypted = bool
kms_key_alias = string
})

iam = object({
create_role = bool
role_name = string
})

enable_imdsv2 = bool
}))
| `{}` | no | | [region](#input\_region) | AWS region used to deploy whole infrastructure | `string` | n/a | yes | diff --git a/examples/panorama_standalone/main.tf b/examples/panorama_standalone/main.tf index dd86487..7d7c7fd 100644 --- a/examples/panorama_standalone/main.tf +++ b/examples/panorama_standalone/main.tf @@ -42,12 +42,21 @@ module "iam" { for_each = var.iam_policies - name_prefix = var.name_prefix - tags = var.tags - role_name = each.value.role_name - create_instance_profile = try(each.value.create_instance_profile, false) - instance_profile_name = try(each.value.instance_profile_name, null) - create_panorama_policy = try(each.value.create_panorama_policy, false) + name_prefix = var.name_prefix + tags = var.tags + role_name = each.value.role_name + create_role = each.value.create_role + principal_role = each.value.principal_role + create_instance_profile = each.value.create_instance_profile + instance_profile_name = each.value.instance_profile_name + create_lambda_policy = each.value.create_lambda_policy + create_bootrap_policy = each.value.create_bootrap_policy + policy_arn = each.value.policy_arn + create_vmseries_policy = each.value.create_vmseries_policy + create_panorama_policy = each.value.create_panorama_policy + custom_policy = each.value.custom_policy + delicense_ssm_param_name = each.value.delicense_ssm_param_name + aws_s3_bucket = each.value.aws_s3_bucket } ### PANORAMA INSTANCES diff --git a/examples/panorama_standalone/variables.tf b/examples/panorama_standalone/variables.tf index de1b0f0..939da50 100644 --- a/examples/panorama_standalone/variables.tf +++ b/examples/panorama_standalone/variables.tf @@ -21,8 +21,6 @@ variable "ssh_key_name" { ### IAM variable "iam_policies" { description = "A map defining an IAM policies, roles etc." - type = any - default = { panorama = { create_instance_profile = true @@ -31,6 +29,31 @@ variable "iam_policies" { create_panorama_policy = true } } + type = map(object({ + role_name = string + create_role = optional(bool, true) + principal_role = optional(string, "ec2.amazonaws.com") + create_instance_profile = optional(bool, false) + instance_profile_name = optional(string) + create_lambda_policy = optional(bool, false) + create_bootrap_policy = optional(bool, false) + policy_arn = optional(string) + create_vmseries_policy = optional(bool, false) + create_panorama_policy = optional(bool, false) + custom_policy = optional(map(object({ + sid = string + effect = string + actions = list(string) + resources = list(string) + condition = optional(object({ + test = string + variable = string + values = list(string) + })) + }))) + delicense_ssm_param_name = optional(string) + aws_s3_bucket = optional(string) + })) } ### VPC diff --git a/examples/panorama_standalone/versions.tf b/examples/panorama_standalone/versions.tf index 6455660..afd605b 100644 --- a/examples/panorama_standalone/versions.tf +++ b/examples/panorama_standalone/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.0, < 2.0.0" + required_version = ">= 1.5.0, < 2.0.0" required_providers { aws = { source = "hashicorp/aws" diff --git a/examples/vmseries_standalone/README.md b/examples/vmseries_standalone/README.md index 88cfdbb..9f440e9 100644 --- a/examples/vmseries_standalone/README.md +++ b/examples/vmseries_standalone/README.md @@ -76,7 +76,7 @@ Use a web browser to access https://x.x.x.x and login with admin and your previo | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | ### Providers @@ -101,7 +101,7 @@ No resources. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. | `any` |
{
"vmseries": {
"aws_s3_bucket": "bucket-paloaltonetworks",
"create_bootrap_policy": true,
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "vmseries_profile_instance",
"role_name": "vmseries_role"
}
}
| no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
map(object({
role_name = string
create_role = optional(bool, true)
principal_role = optional(string, "ec2.amazonaws.com")
create_instance_profile = optional(bool, false)
instance_profile_name = optional(string)
create_lambda_policy = optional(bool, false)
create_bootrap_policy = optional(bool, false)
policy_arn = optional(string)
create_vmseries_policy = optional(bool, false)
create_panorama_policy = optional(bool, false)
custom_policy = optional(map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
})))
delicense_ssm_param_name = optional(string)
aws_s3_bucket = optional(string)
}))
|
{
"vmseries": {
"aws_s3_bucket": "bucket-paloaltonetworks",
"create_bootrap_policy": true,
"create_instance_profile": true,
"create_vmseries_policy": true,
"instance_profile_name": "vmseries_profile_instance",
"role_name": "vmseries_role"
}
}
| no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources (VPCs, EC2 instances, autoscaling groups etc.) | `string` | n/a | yes | | [region](#input\_region) | AWS region used to deploy whole infrastructure | `string` | n/a | yes | | [ssh\_key\_name](#input\_ssh\_key\_name) | Name of the SSH key pair existing in AWS key pairs and used to authenticate to VM-Series or test boxes | `string` | n/a | yes | diff --git a/examples/vmseries_standalone/main.tf b/examples/vmseries_standalone/main.tf index 0484fc4..1b9cf73 100644 --- a/examples/vmseries_standalone/main.tf +++ b/examples/vmseries_standalone/main.tf @@ -43,14 +43,21 @@ module "iam" { for_each = var.iam_policies - name_prefix = var.name_prefix - tags = var.tags - role_name = each.value.role_name - create_instance_profile = try(each.value.create_instance_profile, false) - instance_profile_name = try(each.value.instance_profile_name, null) - create_vmseries_policy = try(each.value.create_vmseries_policy, false) - create_bootrap_policy = try(each.value.create_bootrap_policy, false) - aws_s3_bucket = try(each.value.aws_s3_bucket, null) + name_prefix = var.name_prefix + tags = var.tags + role_name = each.value.role_name + create_role = each.value.create_role + principal_role = each.value.principal_role + create_instance_profile = each.value.create_instance_profile + instance_profile_name = each.value.instance_profile_name + create_lambda_policy = each.value.create_lambda_policy + create_bootrap_policy = each.value.create_bootrap_policy + policy_arn = each.value.policy_arn + create_vmseries_policy = each.value.create_vmseries_policy + create_panorama_policy = each.value.create_panorama_policy + custom_policy = each.value.custom_policy + delicense_ssm_param_name = each.value.delicense_ssm_param_name + aws_s3_bucket = each.value.aws_s3_bucket } ### BOOTSTRAP PACKAGE diff --git a/examples/vmseries_standalone/variables.tf b/examples/vmseries_standalone/variables.tf index 70f66a0..cdfd9b4 100644 --- a/examples/vmseries_standalone/variables.tf +++ b/examples/vmseries_standalone/variables.tf @@ -18,8 +18,6 @@ variable "ssh_key_name" { ### IAM variable "iam_policies" { description = "A map defining an IAM policies, roles etc." - type = any - default = { vmseries = { create_instance_profile = true @@ -30,6 +28,31 @@ variable "iam_policies" { aws_s3_bucket = "bucket-paloaltonetworks" } } + type = map(object({ + role_name = string + create_role = optional(bool, true) + principal_role = optional(string, "ec2.amazonaws.com") + create_instance_profile = optional(bool, false) + instance_profile_name = optional(string) + create_lambda_policy = optional(bool, false) + create_bootrap_policy = optional(bool, false) + policy_arn = optional(string) + create_vmseries_policy = optional(bool, false) + create_panorama_policy = optional(bool, false) + custom_policy = optional(map(object({ + sid = string + effect = string + actions = list(string) + resources = list(string) + condition = optional(object({ + test = string + variable = string + values = list(string) + })) + }))) + delicense_ssm_param_name = optional(string) + aws_s3_bucket = optional(string) + })) } ### VPC diff --git a/examples/vmseries_standalone/versions.tf b/examples/vmseries_standalone/versions.tf index 6455660..afd605b 100644 --- a/examples/vmseries_standalone/versions.tf +++ b/examples/vmseries_standalone/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3.0, < 2.0.0" + required_version = ">= 1.5.0, < 2.0.0" required_providers { aws = { source = "hashicorp/aws" diff --git a/modules/iam/README.md b/modules/iam/README.md index 1fcd1a9..69149a6 100644 --- a/modules/iam/README.md +++ b/modules/iam/README.md @@ -16,7 +16,7 @@ It supports policies for following use cases: | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.0.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | ### Providers @@ -53,7 +53,7 @@ No modules. | [create\_panorama\_policy](#input\_create\_panorama\_policy) | Create a pre-defined panorama policy. | `bool` | `false` | no | | [create\_role](#input\_create\_role) | Create a dedicated role creation of pre-defined policies. | `bool` | `true` | no | | [create\_vmseries\_policy](#input\_create\_vmseries\_policy) | Create a pre-defined vmseries policy. | `bool` | `false` | no | -| [custom\_policy](#input\_custom\_policy) | A custom lambda policy. Multi-statement is supported.
Basic example:
statement1 = {
sid = "1"
effect = "Allow"
actions = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
resources = [
"arn:*:logs:*:*:*"
]
}
statement2 = {
sid = "2"
effect = "Allow"
actions = [
"ec2:AllocateAddress",
"ec2:AssociateAddress",
"ec2:AttachNetworkInterface",
"ec2:CreateNetworkInterface",
"ec2:CreateTags",
"ec2:DescribeAddresses",
"ec2:DescribeInstances",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeTags",
"ec2:DescribeSubnets",
"ec2:DeleteNetworkInterface",
"ec2:DeleteTags",
"ec2:DetachNetworkInterface",
"ec2:DisassociateAddress",
"ec2:ModifyNetworkInterfaceAttribute",
"ec2:ReleaseAddress",
"autoscaling:CompleteLifecycleAction",
"autoscaling:DescribeAutoScalingGroups",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:DeregisterTargets"
]

resources = ["*"]

condition = {
test = "StringEquals"
variable = "aws:ResourceTag/Owner"
values = "user1"
}
}
|
map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
}))
| `null` | no | +| [custom\_policy](#input\_custom\_policy) | A custom IAM policy. Multi-statement is supported.
Basic example:
statement1 = {
sid = "1"
effect = "Allow"
actions = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
resources = [
"arn:*:logs:*:*:*"
]
}
statement2 = {
sid = "2"
effect = "Allow"
actions = [
"ec2:AllocateAddress",
"ec2:AssociateAddress",
"ec2:AttachNetworkInterface",
"ec2:CreateNetworkInterface",
"ec2:CreateTags",
"ec2:DescribeAddresses",
"ec2:DescribeInstances",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeTags",
"ec2:DescribeSubnets",
"ec2:DeleteNetworkInterface",
"ec2:DeleteTags",
"ec2:DetachNetworkInterface",
"ec2:DisassociateAddress",
"ec2:ModifyNetworkInterfaceAttribute",
"ec2:ReleaseAddress",
"autoscaling:CompleteLifecycleAction",
"autoscaling:DescribeAutoScalingGroups",
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:DeregisterTargets"
]

resources = ["*"]

condition = {
test = "StringEquals"
variable = "aws:ResourceTag/Owner"
values = "user1"
}
}
|
map(object({
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
}))
| `null` | no | | [delicense\_ssm\_param\_name](#input\_delicense\_ssm\_param\_name) | Required for IAM de-licensing permissions.
String in Parameter Store with value in below format:
{"username":"ACCOUNT","password":"PASSWORD","panorama1":"IP_ADDRESS1","panorama2":"IP_ADDRESS2","license_manager":"LICENSE_MANAGER_NAME"}"
the format can either be the plain name in case you store it without hierarchy or with a "/" in case you store in in a hierarchy | `string` | `null` | no | | [instance\_profile\_name](#input\_instance\_profile\_name) | Instance profile name. | `string` | `null` | no | | [name\_prefix](#input\_name\_prefix) | Prefix used in names for the resources. (IAM Role, Instance Profile) | `string` | n/a | yes |