Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Expected network connectivity downtime of typically around 20 seconds.
* [workload-vpc](./modules/workload-vpc)
* [Examples](./examples)
* [Basic Example](./examples/basic)
* [Custom Security Group Example](./examples/custom_security_group)
* [Default Example](./examples/default)
* [Existing VPC and subnets Example](./examples/existing_vpc)
* [Hub and Spoke VPC Example](./examples/hub-spoke-delegated-resolver)
Expand Down Expand Up @@ -241,7 +242,7 @@ To attach access management tags to resources in this module, you need the follo
| <a name="input_resource_group_id"></a> [resource\_group\_id](#input\_resource\_group\_id) | The resource group ID where the VPC to be created | `string` | n/a | yes |
| <a name="input_routes"></a> [routes](#input\_routes) | OPTIONAL - Allows you to specify the next hop for packets based on their destination address | <pre>list(<br/> object({<br/> name = string<br/> route_direct_link_ingress = optional(bool)<br/> route_transit_gateway_ingress = optional(bool)<br/> route_vpc_zone_ingress = optional(bool)<br/> routes = optional(<br/> list(<br/> object({<br/> action = optional(string)<br/> zone = number<br/> destination = string<br/> next_hop = string<br/> })<br/> ))<br/> })<br/> )</pre> | `[]` | no |
| <a name="input_routing_table_name"></a> [routing\_table\_name](#input\_routing\_table\_name) | The name to give the provisioned routing tables. If not set, the module generates a name based on the `prefix` and `name` variables. | `string` | `null` | no |
| <a name="input_security_group_rules"></a> [security\_group\_rules](#input\_security\_group\_rules) | A list of security group rules to be added to the default vpc security group (default empty) | <pre>list(<br/> object({<br/> name = string<br/> direction = string<br/> remote = optional(string)<br/> tcp = optional(<br/> object({<br/> port_max = optional(number)<br/> port_min = optional(number)<br/> })<br/> )<br/> udp = optional(<br/> object({<br/> port_max = optional(number)<br/> port_min = optional(number)<br/> })<br/> )<br/> icmp = optional(<br/> object({<br/> type = optional(number)<br/> code = optional(number)<br/> })<br/> )<br/> })<br/> )</pre> | `[]` | no |
| <a name="input_security_group_rules"></a> [security\_group\_rules](#input\_security\_group\_rules) | A list of security group rules to be added to the default vpc security group (default empty) | <pre>list(<br/> object({<br/> name = string<br/> direction = string<br/> remote = optional(string)<br/> local = optional(string)<br/> ip_version = optional(string)<br/> tcp = optional(<br/> object({<br/> port_max = optional(number)<br/> port_min = optional(number)<br/> })<br/> )<br/> udp = optional(<br/> object({<br/> port_max = optional(number)<br/> port_min = optional(number)<br/> })<br/> )<br/> icmp = optional(<br/> object({<br/> type = optional(number)<br/> code = optional(number)<br/> })<br/> )<br/> })<br/> )</pre> | `[]` | no |
| <a name="input_skip_custom_resolver_hub_creation"></a> [skip\_custom\_resolver\_hub\_creation](#input\_skip\_custom\_resolver\_hub\_creation) | Indicates whether to skip the configuration of a custom resolver in the hub VPC. Only relevant if enable\_hub is set to true. | `bool` | `false` | no |
| <a name="input_skip_spoke_auth_policy"></a> [skip\_spoke\_auth\_policy](#input\_skip\_spoke\_auth\_policy) | Set to true to skip the creation of an authorization policy between the DNS resolution spoke and hub, only enable this if a policy already exists between these two VPCs. See https://cloud.ibm.com/docs/vpc?topic=vpc-vpe-dns-sharing-s2s-auth&interface=ui for more details. | `bool` | `false` | no |
| <a name="input_subnets"></a> [subnets](#input\_subnets) | List of subnets for the vpc. For each item in each array, a subnet will be created. Items can be either CIDR blocks or total ipv4 addresses. Public gateways will be enabled only in zones where a gateway has been created | <pre>object({<br/> zone-1 = list(object({<br/> name = string<br/> cidr = string<br/> public_gateway = optional(bool)<br/> acl_name = string<br/> no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true<br/> subnet_tags = optional(list(string), [])<br/> }))<br/> zone-2 = optional(list(object({<br/> name = string<br/> cidr = string<br/> public_gateway = optional(bool)<br/> acl_name = string<br/> no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true<br/> subnet_tags = optional(list(string), [])<br/> })))<br/> zone-3 = optional(list(object({<br/> name = string<br/> cidr = string<br/> public_gateway = optional(bool)<br/> acl_name = string<br/> no_addr_prefix = optional(bool, false) # do not automatically add address prefix for subnet, overrides other conditions if set to true<br/> subnet_tags = optional(list(string), [])<br/> })))<br/> })</pre> | <pre>{<br/> "zone-1": [<br/> {<br/> "acl_name": "vpc-acl",<br/> "cidr": "10.10.10.0/24",<br/> "name": "subnet-a",<br/> "no_addr_prefix": false,<br/> "public_gateway": true<br/> }<br/> ],<br/> "zone-2": [<br/> {<br/> "acl_name": "vpc-acl",<br/> "cidr": "10.20.10.0/24",<br/> "name": "subnet-b",<br/> "no_addr_prefix": false,<br/> "public_gateway": true<br/> }<br/> ],<br/> "zone-3": [<br/> {<br/> "acl_name": "vpc-acl",<br/> "cidr": "10.30.10.0/24",<br/> "name": "subnet-c",<br/> "no_addr_prefix": false,<br/> "public_gateway": false<br/> }<br/> ]<br/>}</pre> | no |
Expand Down
10 changes: 6 additions & 4 deletions default_security_group.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ locals {
}

resource "ibm_is_security_group_rule" "default_vpc_rule" {
for_each = local.security_group_rule_object
group = var.create_vpc == true ? ibm_is_vpc.vpc[0].default_security_group : data.ibm_is_vpc.vpc.default_security_group
direction = each.value.direction
remote = each.value.remote
for_each = local.security_group_rule_object
group = var.create_vpc == true ? ibm_is_vpc.vpc[0].default_security_group : data.ibm_is_vpc.vpc.default_security_group
direction = each.value.direction
remote = each.value.remote
local = each.value.local
ip_version = each.value.ip_version

dynamic "tcp" {
for_each = each.value.tcp == null ? [] : [each.value]
Expand Down
8 changes: 8 additions & 0 deletions examples/custom_security_group/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Custom Security Group Example

A simple example to provision a Secure Landing Zone (SLZ) Virtual Private Cloud (VPC) with Security Group Rules set.

The following resources are provisioned by this example:

* A new resource group, if an existing one is not passed in.
* An IBM Virtual Private Cloud (VPC) with custom security group rules.
33 changes: 33 additions & 0 deletions examples/custom_security_group/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

##############################################################################
# Resource Group
##############################################################################

module "resource_group" {
source = "terraform-ibm-modules/resource-group/ibm"
version = "1.3.0"
# if an existing resource group is not set (null) create a new one using prefix
resource_group_name = var.resource_group == null ? "${var.prefix}-resource-group" : null
existing_resource_group_name = var.resource_group
}

##############################################################################
# Create new VPC
# (if var.vpc_id is null, create a new VPC)
##############################################################################

module "vpc" {
source = "../.."
resource_group_id = module.resource_group.resource_group_id
region = var.region
prefix = var.prefix
name = "sg-vpc"
tags = var.resource_tags
security_group_rules = [{
name = "allow-all-inbound-sg"
direction = "inbound"
remote = "0.0.0.0/0" # source of the traffic. 0.0.0.0/0 traffic from all across the internet.
local = "0.0.0.0/0" # A CIDR block of 0.0.0.0/0 allows traffic to all local IP addresses (or from all local IP addresses, for outbound rules).
ip_version = "ipv4"
}]
}
13 changes: 13 additions & 0 deletions examples/custom_security_group/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
##############################################################################
# Outputs
##############################################################################

output "vpc_id" {
value = module.vpc.vpc_id
description = "VPC id"
}

output "vpc_crn" {
value = module.vpc.vpc_crn
description = "VPC crn"
}
4 changes: 4 additions & 0 deletions examples/custom_security_group/provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
provider "ibm" {
ibmcloud_api_key = var.ibmcloud_api_key
region = var.region
}
27 changes: 27 additions & 0 deletions examples/custom_security_group/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
variable "ibmcloud_api_key" {
description = "APIkey that's associated with the account to provision resources to"
type = string
sensitive = true
}

variable "region" {
description = "The region to which to deploy the VPC"
type = string
}

variable "prefix" {
description = "The prefix that you would like to append to your resources"
type = string
}

variable "resource_group" {
type = string
description = "An existing resource group name to use for this example, if unset a new resource group will be created"
default = null
}

variable "resource_tags" {
description = "List of Tags for the resource created"
type = list(string)
default = null
}
11 changes: 11 additions & 0 deletions examples/custom_security_group/version.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
terraform {
required_version = ">= 1.9.0"
required_providers {
# Ensure that there is always 1 example locked into the lowest provider version of the range defined in the main
# module's version.tf (basic), and 1 example that will always use the latest provider version.
ibm = {
source = "IBM-Cloud/ibm"
version = ">=1.59.0"
}
}
}
2 changes: 1 addition & 1 deletion modules/management-vpc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ No resources.
| <a name="input_default_network_acl_name"></a> [default\_network\_acl\_name](#input\_default\_network\_acl\_name) | Override default ACL name | `string` | `null` | no |
| <a name="input_default_routing_table_name"></a> [default\_routing\_table\_name](#input\_default\_routing\_table\_name) | Override default VPC routing table name | `string` | `null` | no |
| <a name="input_default_security_group_name"></a> [default\_security\_group\_name](#input\_default\_security\_group\_name) | Override default VPC security group name | `string` | `null` | no |
| <a name="input_default_security_group_rules"></a> [default\_security\_group\_rules](#input\_default\_security\_group\_rules) | Override default security group rules | <pre>list(<br/> object({<br/> name = string<br/> direction = string<br/> remote = string<br/> tcp = optional(<br/> object({<br/> port_max = optional(number)<br/> port_min = optional(number)<br/> })<br/> )<br/> udp = optional(<br/> object({<br/> port_max = optional(number)<br/> port_min = optional(number)<br/> })<br/> )<br/> icmp = optional(<br/> object({<br/> type = optional(number)<br/> code = optional(number)<br/> })<br/> )<br/> })<br/> )</pre> | `[]` | no |
| <a name="input_default_security_group_rules"></a> [default\_security\_group\_rules](#input\_default\_security\_group\_rules) | Override default security group rules | <pre>list(<br/> object({<br/> name = string<br/> direction = string<br/> remote = optional(string)<br/> local = optional(string)<br/> ip_version = optional(string)<br/> tcp = optional(<br/> object({<br/> port_max = optional(number)<br/> port_min = optional(number)<br/> })<br/> )<br/> udp = optional(<br/> object({<br/> port_max = optional(number)<br/> port_min = optional(number)<br/> })<br/> )<br/> icmp = optional(<br/> object({<br/> type = optional(number)<br/> code = optional(number)<br/> })<br/> )<br/> })<br/> )</pre> | `[]` | no |
| <a name="input_enable_vpc_flow_logs"></a> [enable\_vpc\_flow\_logs](#input\_enable\_vpc\_flow\_logs) | Enable VPC Flow Logs, it will create Flow logs collector if set to true | `bool` | `false` | no |
| <a name="input_existing_cos_bucket_name"></a> [existing\_cos\_bucket\_name](#input\_existing\_cos\_bucket\_name) | Name of the COS bucket to collect VPC flow logs | `string` | `null` | no |
| <a name="input_existing_cos_instance_guid"></a> [existing\_cos\_instance\_guid](#input\_existing\_cos\_instance\_guid) | GUID of the COS instance to create Flow log collector | `string` | `null` | no |
Expand Down
8 changes: 5 additions & 3 deletions modules/management-vpc/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ variable "default_security_group_rules" {
description = "Override default security group rules"
type = list(
object({
name = string
direction = string
remote = string
name = string
direction = string
remote = optional(string)
local = optional(string)
ip_version = optional(string)
tcp = optional(
object({
port_max = optional(number)
Expand Down
2 changes: 1 addition & 1 deletion modules/workload-vpc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ No resources.
| <a name="input_default_network_acl_name"></a> [default\_network\_acl\_name](#input\_default\_network\_acl\_name) | Override default ACL name | `string` | `null` | no |
| <a name="input_default_routing_table_name"></a> [default\_routing\_table\_name](#input\_default\_routing\_table\_name) | Override default VPC routing table name | `string` | `null` | no |
| <a name="input_default_security_group_name"></a> [default\_security\_group\_name](#input\_default\_security\_group\_name) | Override default VPC security group name | `string` | `null` | no |
| <a name="input_default_security_group_rules"></a> [default\_security\_group\_rules](#input\_default\_security\_group\_rules) | Override default security group rules | <pre>list(<br/> object({<br/> name = string<br/> direction = string<br/> remote = string<br/> tcp = optional(<br/> object({<br/> port_max = optional(number)<br/> port_min = optional(number)<br/> })<br/> )<br/> udp = optional(<br/> object({<br/> port_max = optional(number)<br/> port_min = optional(number)<br/> })<br/> )<br/> icmp = optional(<br/> object({<br/> type = optional(number)<br/> code = optional(number)<br/> })<br/> )<br/> })<br/> )</pre> | `[]` | no |
| <a name="input_default_security_group_rules"></a> [default\_security\_group\_rules](#input\_default\_security\_group\_rules) | Override default security group rules | <pre>list(<br/> object({<br/> name = string<br/> direction = string<br/> remote = optional(string)<br/> local = optional(string)<br/> ip_version = optional(string)<br/> tcp = optional(<br/> object({<br/> port_max = optional(number)<br/> port_min = optional(number)<br/> })<br/> )<br/> udp = optional(<br/> object({<br/> port_max = optional(number)<br/> port_min = optional(number)<br/> })<br/> )<br/> icmp = optional(<br/> object({<br/> type = optional(number)<br/> code = optional(number)<br/> })<br/> )<br/> })<br/> )</pre> | `[]` | no |
| <a name="input_enable_vpc_flow_logs"></a> [enable\_vpc\_flow\_logs](#input\_enable\_vpc\_flow\_logs) | Enable VPC Flow Logs, it will create Flow logs collector if set to true | `bool` | `false` | no |
| <a name="input_existing_cos_bucket_name"></a> [existing\_cos\_bucket\_name](#input\_existing\_cos\_bucket\_name) | Name of the COS bucket to collect VPC flow logs | `string` | `null` | no |
| <a name="input_existing_cos_instance_guid"></a> [existing\_cos\_instance\_guid](#input\_existing\_cos\_instance\_guid) | GUID of the COS instance to create Flow log collector | `string` | `null` | no |
Expand Down
8 changes: 5 additions & 3 deletions modules/workload-vpc/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@ variable "default_security_group_rules" {
description = "Override default security group rules"
type = list(
object({
name = string
direction = string
remote = string
name = string
direction = string
remote = optional(string)
local = optional(string)
ip_version = optional(string)
tcp = optional(
object({
port_max = optional(number)
Expand Down
2 changes: 2 additions & 0 deletions solutions/fully-configurable/DA-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ This variable configuration allows you to specify the list of security group rul
- `name` (required): The name of the security group rule.
- `direction` (required): The direction of the traffic. Allowed values are `inbound` or `outbound`.
- `remote` (optional): Security group ID or an IP address or a CIDR block.
- `local` (optional): The local IP address or range of local IP addresses to which this rule will allow inbound traffic (or from which, for outbound traffic).
- `ip_version` (optional): The IP version to enforce.
- `tcp` (optional):
- `port_min`
- `port_max`
Expand Down
8 changes: 5 additions & 3 deletions solutions/fully-configurable/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -327,9 +327,11 @@ variable "security_group_rules" {
default = []
type = list(
object({
name = string
direction = string
remote = optional(string)
name = string
direction = string
remote = optional(string)
local = optional(string)
ip_version = optional(string)
tcp = optional(
object({
port_max = optional(number)
Expand Down
15 changes: 15 additions & 0 deletions tests/other_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,18 @@ func TestRunSpecificZoneExample(t *testing.T) {
assert.Nil(t, err, "This should not have errored")
assert.NotNil(t, output, "Expected some output")
}

func TestRunCustomSecurityGroupExample(t *testing.T) {
t.Parallel()

options := testhelper.TestOptionsDefaultWithVars(&testhelper.TestOptions{
Testing: t,
TerraformDir: customSecurityGroupExampleTerraformDir,
Prefix: "sg-slz",
ResourceGroup: resourceGroup,
})

output, err := options.RunTestConsistency()
assert.Nil(t, err, "This should not have errored")
assert.NotNil(t, output, "Expected some output")
}
1 change: 1 addition & 0 deletions tests/pr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
)

const basicExampleTerraformDir = "examples/basic"
const customSecurityGroupExampleTerraformDir = "examples/custom_security_group"
const defaultExampleTerraformDir = "examples/default"
const landingZoneExampleTerraformDir = "examples/landing_zone"
const hubAndSpokeDelegatedExampleTerraformDir = "examples/hub-spoke-delegated-resolver"
Expand Down
8 changes: 5 additions & 3 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -425,9 +425,11 @@ variable "security_group_rules" {
default = []
type = list(
object({
name = string
direction = string
remote = optional(string)
name = string
direction = string
remote = optional(string)
local = optional(string)
ip_version = optional(string)
tcp = optional(
object({
port_max = optional(number)
Expand Down