diff --git a/examples/centralized_design/README.md b/examples/centralized_design/README.md
index 23d5972..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 |
@@ -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](#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 |
@@ -90,19 +91,11 @@ 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 |
-| [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
@@ -110,6 +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({| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.
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)
}))
gwlbs = {|
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
map(object({| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
name = string
vpc = string
subnet_group = string
}))
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)
}))
{| 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.
"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"
}
}
natgws = {|
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
map(object({| `{}` | no | | [panorama\_attachment](#input\_panorama\_attachment) | A object defining TGW attachment and CIDR for Panorama.
name = string
vpc = string
subnet_group = string
}))
panorama = {|
transit_gateway_attachment_id = "tgw-attach-123456789"
vpc_cidr = "10.255.0.0/24"
}
object({| `null` | no | diff --git a/examples/centralized_design/main.tf b/examples/centralized_design/main.tf index 284dc65..b951a6c 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 = <
transit_gateway_attachment_id = string
vpc_cidr = string
})
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({| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.
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)
}))
gwlbs = {|
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
map(object({| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
name = string
vpc = string
subnet_group = string
}))
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)
}))
{| 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.
"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"
}
}
natgws = {|
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
map(object({| `{}` | no | | [panorama\_attachment](#input\_panorama\_attachment) | A object defining TGW attachment and CIDR for Panorama.
name = string
vpc = string
subnet_group = string
}))
panorama = {|
transit_gateway_attachment_id = "tgw-attach-123456789"
vpc_cidr = "10.255.0.0/24"
}
object({| `null` | no | diff --git a/examples/centralized_design_autoscale/main.tf b/examples/centralized_design_autoscale/main.tf index 6c3e6be..26827d2 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 = <
transit_gateway_attachment_id = string
vpc_cidr = string
})
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({| `{}` | no | | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.
name = string
vpc = string
subnet_group = string
description = string
security_rules = map(any)
log_profiles = map(any)
profile_config = map(any)
}))
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({| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
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
}))
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)
}))
{| 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.
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "combined_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
}
}
natgws = {|
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
map(object({| `{}` | 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..55e7a1a 100644 --- a/examples/cloudngfw_combined_design/main.tf +++ b/examples/cloudngfw_combined_design/main.tf @@ -128,6 +128,30 @@ 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_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 #### data "aws_ami" "this" { @@ -153,34 +177,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 = <
name = string
vpc = string
subnet_group = string
}))
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({| `{}` | no | | [gwlb\_endpoints](#input\_gwlb\_endpoints) | A map defining GWLB endpoints.
name = string
vpc = string
subnet_group = string
description = string
security_rules = map(any)
log_profiles = map(any)
profile_config = map(any)
}))
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({| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
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
}))
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)
}))
{| 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.
"spoke": {
"create_instance_profile": true,
"instance_profile_name": "isolated_spoke_profile",
"policy_arn": "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore",
"role_name": "spoke_role"
}
}
natgws = {|
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
map(object({| `{}` | 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..e1b68a2 100644 --- a/examples/cloudngfw_isolated_design/main.tf +++ b/examples/cloudngfw_isolated_design/main.tf @@ -92,6 +92,30 @@ 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_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 #### data "aws_ami" "this" { @@ -117,34 +141,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 = <
name = string
vpc = string
subnet_group = string
}))
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({| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.
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)
}))
gwlbs = {|
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
map(object({| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
name = string
vpc = string
subnet_group = string
}))
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)
}))
{| 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.
"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"
}
}
natgws = {|
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
map(object({| `{}` | no | | [panorama\_attachment](#input\_panorama\_attachment) | An object defining TGW attachment and CIDR for Panorama.
name = string
vpc = string
subnet_group = string
}))
panorama = {|
transit_gateway_attachment_id = "tgw-attach-123456789"
vpc_cidr = "10.255.0.0/24"
}
object({| `null` | no | diff --git a/examples/combined_design/main.tf b/examples/combined_design/main.tf index 3ea935c..cc2d24d 100644 --- a/examples/combined_design/main.tf +++ b/examples/combined_design/main.tf @@ -157,65 +157,29 @@ 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 = <
transit_gateway_attachment_id = string
vpc_cidr = string
})
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({| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.
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)
}))
gwlbs = {|
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
map(object({| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
name = string
vpc = string
subnet_group = string
}))
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)
}))
{| 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.
"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"
}
}
natgws = {|
security_nat_gw = {
name = "natgw"
vpc = "security_vpc"
subnet_group = "natgw"
}
}
map(object({| `{}` | no | | [panorama\_attachment](#input\_panorama\_attachment) | A object defining TGW attachment and CIDR for Panorama.
name = string
vpc = string
subnet_group = string
}))
panorama = {|
transit_gateway_attachment_id = "tgw-attach-123456789"
vpc_cidr = "10.255.0.0/24"
}
object({| `null` | no | diff --git a/examples/combined_design_autoscale/main.tf b/examples/combined_design_autoscale/main.tf index f74447b..7444f1e 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 = <
transit_gateway_attachment_id = string
vpc_cidr = string
})
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({| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.
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)
}))
gwlbs = {|
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
map(object({| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
name = string
vpc = string
subnet_group = string
}))
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)
}))
{| 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.
"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"
}
}
panorama = {|
security_vpc = "security_vpc"
peering_vpc_id = "vpc-1234567890"
vpc_cidr = "10.255.0.0/24"
}
object({| `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..12eb566 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 = <
security_vpc = string
peering_vpc_id = string
vpc_cidr = string
})
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({| `{}` | no | | [gwlbs](#input\_gwlbs) | A map defining Gateway Load Balancers.
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)
}))
gwlbs = {|
security_gwlb = {
name = "security-gwlb"
vpc = "security_vpc"
subnet_group = "gwlb"
}
}
map(object({| `{}` | no | +| [iam\_policies](#input\_iam\_policies) | A map defining an IAM policies, roles etc. |
name = string
vpc = string
subnet_group = string
}))
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)
}))
{| 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.
"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"
}
}
panorama = {|
security_vpc = "security_vpc"
peering_vpc_id = "vpc-1234567890"
vpc_cidr = "10.255.0.0/24"
}
object({| `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..74251cb 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 = <
security_vpc = string
peering_vpc_id = string
vpc_cidr = string
})
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)
}))
{| 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
"panorama": {
"create_instance_profile": true,
"create_panorama_policy": true,
"instance_profile_name": "panorama_profile",
"role_name": "panorama_role"
}
}
{|
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({| `{}` | no | | [region](#input\_region) | AWS region used to deploy whole infrastructure | `string` | n/a | yes | diff --git a/examples/panorama_standalone/example.tfvars b/examples/panorama_standalone/example.tfvars index 9a66240..c61bcde 100644 --- a/examples/panorama_standalone/example.tfvars +++ b/examples/panorama_standalone/example.tfvars @@ -79,7 +79,7 @@ panoramas = { } } - panos_version = "10.2.3" + panos_version = "10.2.8" network = { vpc = "management_vpc" diff --git a/examples/panorama_standalone/main.tf b/examples/panorama_standalone/main.tf index 508a615..7d7c7fd 100644 --- a/examples/panorama_standalone/main.tf +++ b/examples/panorama_standalone/main.tf @@ -35,77 +35,28 @@ 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 = <
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
}))
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)
}))
{| 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
"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"
}
}
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({| `{}` | no | +| [vmseries](#input\_vmseries) | A map defining VM-Series instances
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)
}))
}))
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({| `{}` | no | | [vpcs](#input\_vpcs) | A map defining VPCs with security groups and subnets.
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)
}))
}))
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({| `{}` | 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..1b9cf73 100644 --- a/examples/vmseries_standalone/main.tf +++ b/examples/vmseries_standalone/main.tf @@ -36,44 +36,28 @@ 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_policy" "this" { - for_each = { for vmseries in local.vmseries_instances : "${vmseries.group}-${vmseries.instance}" => vmseries } - role = module.bootstrap[each.key].iam_role_name - policy = <
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
}))
}))
interfaces = {| `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 |
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"
},
]
list(object({| `[]` | no | | [lambda\_execute\_pip\_install\_once](#input\_lambda\_execute\_pip\_install\_once) | Flag used in local-exec command installing Python packages required by Lambda.
arn = string
port = string
}))
{| 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 = <
"dhcp-accept-server-domain": "yes",
"dhcp-accept-server-hostname": "yes",
"dhcp-send-client-id": "yes",
"dhcp-send-hostname": "yes"
}
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\_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 IAM policy. Multi-statement is supported.
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({| `null` | no | +| [delicense\_ssm\_param\_name](#input\_delicense\_ssm\_param\_name) | Required for IAM de-licensing permissions.
sid = string
effect = string
actions = list(string)
resources = list(string)
condition = optional(object({
test = string
variable = string
values = list(string)
}))
}))
{"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 | +| [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/AmazonSSMManagedInstanceCorepolicy. | `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 + +| 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..4a3ee77 --- /dev/null +++ b/modules/iam/main.tf @@ -0,0 +1,283 @@ +### IAM ROLES AND POLICIES ### + +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}", "") + + 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.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.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:${local.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:${local.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:::${local.aws_s3_bucket}"] + } + statement2 = { + sid = "2" + effect = "Allow" + actions = ["s3:GetObject"] + resources = ["arn:${data.aws_partition.this.partition}:s3:::${local.aws_s3_bucket}/*"] + } + } + + 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 + definition = try(var.custom_policy, null) + }, + "lambda_execute" = { + enable = var.create_lambda_policy ? true : false + definition = local.lambda_execute_policy + }, + "lambda_delicense" = { + enable = var.create_lambda_policy && var.delicense_ssm_param_name != null ? true : false + definition = local.lambda_delicense_policy + }, + "vmseries" = { + enable = var.create_vmseries_policy + definition = local.vmseries_policy + }, + "bootstrap" = { + 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 + } + } +} + +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.instance_profile_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..134d008 --- /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[0] : null +} + +output "iam_role" { + description = "The role used for policies." + 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 new file mode 100644 index 0000000..34b6c2d --- /dev/null +++ b/modules/iam/variables.tf @@ -0,0 +1,160 @@ +variable "name_prefix" { + description = "Prefix used in names for the resources. (IAM Role, Instance Profile)" + type = string +} + +variable "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 + default = null +} + +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 "role_name" { + description = "A role name, required for the service." + type = string +} + +variable "create_instance_profile" { + description = "Create an instance profile." + type = bool + default = false +} + +variable "instance_profile_name" { + description = "Instance profile 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 "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 + default = null +} + +variable "custom_policy" { + description = <<-EOF + 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" + } + } + ``` + 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 + 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 + 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 +} diff --git a/modules/iam/versions.tf b/modules/iam/versions.tf new file mode 100644 index 0000000..3bd8c04 --- /dev/null +++ b/modules/iam/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.5.0, < 2.0.0" + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.17" + } + } +}