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({
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. |
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 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 = < [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 | @@ -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. |
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 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 = < [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 | @@ -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. |
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 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 = < [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 | @@ -100,6 +100,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 | @@ -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. |
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 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 = < [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | ### Providers @@ -109,6 +109,7 @@ If no errors occurred during deployment, configure the VM-Series machines as exp |------|--------|---------| | [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. |
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 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 = < [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | ### Providers @@ -231,6 +231,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 | | [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. |
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 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 = < [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | ### Providers @@ -80,6 +80,7 @@ To enable access from the session manager, the Internet connection for a public |------|--------|---------| | [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. |
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 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 = < [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | ### Providers @@ -188,6 +188,7 @@ statistic = "Maximum" |------|--------|---------| | [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. |
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 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 = < [terraform](#requirement\_terraform) | >= 1.3.0, < 2.0.0 | +| [terraform](#requirement\_terraform) | >= 1.5.0, < 2.0.0 | | [aws](#requirement\_aws) | ~> 5.17 | ### 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. |
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/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 = < 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 +### 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 } ### PANORAMA INSTANCES @@ -136,12 +87,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..939da50 100644 --- a/examples/panorama_standalone/variables.tf +++ b/examples/panorama_standalone/variables.tf @@ -18,6 +18,44 @@ variable "ssh_key_name" { type = string } +### IAM +variable "iam_policies" { + description = "A map defining an IAM policies, roles etc." + default = { + panorama = { + create_instance_profile = true + instance_profile_name = "panorama_profile" + role_name = "panorama_role" + 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 variable "vpcs" { description = <<-EOF 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 9ef1765..9f440e9 100644 --- a/examples/vmseries_standalone/README.md +++ b/examples/vmseries_standalone/README.md @@ -76,41 +76,37 @@ 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 -| 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. |
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 | | [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..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 = < 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 +106,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..cdfd9b4 100644 --- a/examples/vmseries_standalone/variables.tf +++ b/examples/vmseries_standalone/variables.tf @@ -15,6 +15,46 @@ variable "ssh_key_name" { type = string } +### IAM +variable "iam_policies" { + description = "A map defining an IAM policies, roles etc." + 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" + } + } + 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 variable "vpcs" { description = <<-EOF @@ -176,6 +216,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 +256,8 @@ variable "vmseries" { az = string })) + bucket_name = string + bootstrap_options = object({ mgmt-interface-swap = string panorama-server = string 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/asg/README.md b/modules/asg/README.md index ceefd7f..df711db 100644 --- a/modules/asg/README.md +++ b/modules/asg/README.md @@ -42,9 +42,6 @@ No modules. | [aws_cloudwatch_event_rule.instance_terminate_event_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) | resource | | [aws_cloudwatch_event_target.instance_launch_event](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | | [aws_cloudwatch_event_target.instance_terminate_event](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) | resource | -| [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | -| [aws_iam_role_policy.lambda_iam_policy_default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_iam_role_policy.lambda_iam_policy_delicense](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_lambda_function.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) | resource | | [aws_lambda_permission.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission) | resource | | [aws_launch_template.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/launch_template) | resource | @@ -53,7 +50,6 @@ No modules. | [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 | | [aws_kms_alias.ebs_kms](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 @@ -75,6 +71,7 @@ No modules. | [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 = < [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 = < +### Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.5.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 | +| [aws_region.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | 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\_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.
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 | +| [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 + +| 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" + } + } +}