Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: initial commit for DA #915

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ To attach access management tags to resources in this module, you need the follo
| [ibm_is_vpc_dns_resolution_binding.vpc_dns_resolution_binding_id](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/is_vpc_dns_resolution_binding) | resource |
| [ibm_is_vpc_routing_table.route_table](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/is_vpc_routing_table) | resource |
| [ibm_is_vpc_routing_table_route.routing_table_routes](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/is_vpc_routing_table_route) | resource |
| [ibm_is_vpn_gateway.gateway](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/is_vpn_gateway) | resource |
| [ibm_resource_instance.dns_instance_hub](https://registry.terraform.io/providers/IBM-Cloud/ibm/latest/docs/resources/resource_instance) | resource |
| [time_sleep.wait_for_authorization_policy](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource |
| [time_sleep.wait_for_vpc_creation_data](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep) | resource |
Expand Down Expand Up @@ -203,6 +204,7 @@ To attach access management tags to resources in this module, you need the follo
| <a name="input_enable_hub_vpc_crn"></a> [enable\_hub\_vpc\_crn](#input\_enable\_hub\_vpc\_crn) | Indicates whether Hub VPC CRN is passed. | `bool` | `false` | no |
| <a name="input_enable_hub_vpc_id"></a> [enable\_hub\_vpc\_id](#input\_enable\_hub\_vpc\_id) | Indicates whether Hub VPC ID is passed. | `bool` | `false` | no |
| <a name="input_enable_vpc_flow_logs"></a> [enable\_vpc\_flow\_logs](#input\_enable\_vpc\_flow\_logs) | Flag to enable vpc flow logs. If true, flow log collector will be created | `bool` | `false` | no |
| <a name="input_enable_vpn_gateways"></a> [enable\_vpn\_gateways](#input\_enable\_vpn\_gateways) | Set to true to add VPN gateways. If true, VPN gateways will be created using the variable 'vpn\_gateways'. | `bool` | `false` | 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 |
| <a name="input_existing_dns_instance_id"></a> [existing\_dns\_instance\_id](#input\_existing\_dns\_instance\_id) | Id of an existing dns instance in which the custom resolver is created. Only relevant if enable\_hub is set to true. | `string` | `null` | no |
| <a name="input_existing_storage_bucket_name"></a> [existing\_storage\_bucket\_name](#input\_existing\_storage\_bucket\_name) | Name of the COS bucket to collect VPC flow logs | `string` | `null` | no |
Expand Down Expand Up @@ -232,6 +234,7 @@ To attach access management tags to resources in this module, you need the follo
| <a name="input_use_existing_dns_instance"></a> [use\_existing\_dns\_instance](#input\_use\_existing\_dns\_instance) | Whether to use an existing dns instance. If true, existing\_dns\_instance\_id must be set. | `bool` | `false` | no |
| <a name="input_use_public_gateways"></a> [use\_public\_gateways](#input\_use\_public\_gateways) | Create a public gateway in any of the three zones with `true`. | <pre>object({<br/> zone-1 = optional(bool)<br/> zone-2 = optional(bool)<br/> zone-3 = optional(bool)<br/> })</pre> | <pre>{<br/> "zone-1": true,<br/> "zone-2": false,<br/> "zone-3": false<br/>}</pre> | no |
| <a name="input_vpc_flow_logs_name"></a> [vpc\_flow\_logs\_name](#input\_vpc\_flow\_logs\_name) | The name to give the provisioned VPC flow logs. If not set, the module generates a name based on the `prefix` and `name` variables. | `string` | `null` | no |
| <a name="input_vpn_gateways"></a> [vpn\_gateways](#input\_vpn\_gateways) | List of VPN gateways to create. | <pre>list(<br/> object({<br/> name = string<br/> vpc_name = string<br/> subnet_name = string # Do not include prefix, use same name as in `var.subnets`<br/> mode = optional(string)<br/> resource_group = optional(string)<br/> access_tags = optional(list(string), [])<br/> })<br/> )</pre> | `[]` | no |

### Outputs

Expand Down
24 changes: 23 additions & 1 deletion main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ resource "ibm_is_flow_log" "flow_logs" {

##############################################################################
# DNS ZONE
# ##############################################################################
###############################################################################

resource "ibm_dns_zone" "dns_zone" {
count = var.enable_hub && !var.skip_custom_resolver_hub_creation && alltrue([var.dns_zone_name != null, var.dns_zone_name != ""]) ? 1 : 0
Expand Down Expand Up @@ -406,6 +406,28 @@ resource "ibm_dns_resource_record" "dns_record" {

locals {
record_ids = [for record in ibm_dns_resource_record.dns_record : element(split("/", record.id), 2)]

# Convert the vpn_gateway input from list to a map
vpn_gateway_map = !var.enable_vpn_gateways ? {} : { for gateway in var.vpn_gateways : gateway.name => gateway }

}

##############################################################################
# Create VPN Gateways
##############################################################################

resource "ibm_is_vpn_gateway" "gateway" {
for_each = local.vpn_gateway_map
name = "${var.prefix}-${each.key}"
subnet = each.value.subnet_name
mode = each.value.mode
resource_group = each.value.resource_group == null ? var.resource_group_id : each.value.resource_group
tags = var.tags
access_tags = each.value.access_tags

timeouts {
delete = "1h"
}
}

##############################################################################
11 changes: 11 additions & 0 deletions solutions/fully-configurable/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# IBM VPC deployable architecture

This deployable architecture supports provisioning the following resources:

- A new resource group if one is not passed in.
- A VPC.


![vpc-deployable-architecture](../../reference-architecture/vpc-quickstart-da.svg)

:exclamation: **Important:** This solution is not intended to be called by other modules because it contains a provider configuration and is not compatible with the `for_each`, `count`, and `depends_on` arguments. For more information, see [Providers Within Modules](https://developer.hashicorp.com/terraform/language/modules/develop/providers).
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"ibmcloud_api_key": $VALIDATION_APIKEY,
"region": "us-south",
"resource_tags": $TAGS,
"existing_resource_group_name": $PREFIX
}
136 changes: 136 additions & 0 deletions solutions/fully-configurable/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
locals {
prefix = var.prefix != null ? (var.prefix != "" ? var.prefix : null) : null
}

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

module "resource_group" {
source = "terraform-ibm-modules/resource-group/ibm"
version = "1.1.6"
existing_resource_group_name = var.existing_resource_group_name
}

#############################################################################
# COS Bucket for VPC flow logs
#############################################################################

# parse COS details from the existing COS instance CRN
module "existing_cos_crn_parser" {
count = var.existing_cos_instance_crn != null ? 1 : 0
source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser"
version = "1.1.0"
crn = var.existing_cos_instance_crn
}

locals {
bucket_name = try("${local.prefix}-${var.cos_bucket_name}", var.cos_bucket_name)

bucket_config = [{
access_tags = var.access_tags
bucket_name = local.bucket_name
kms_encryption_enabled = var.kms_encryption_enabled_bucket
kms_guid = var.kms_encryption_enabled_bucket ? module.existing_kms_instance_crn_parser[0].service_instance : null
kms_key_crn = var.kms_encryption_enabled_bucket ? var.existing_kms_instance_crn : null
skip_iam_authorization_policy = var.skip_cos_kms_auth_policy
management_endpoint_type = var.management_endpoint_type_for_bucket
storage_class = var.cos_bucket_class
resource_instance_id = var.existing_cos_instance_crn
region_location = var.region
force_delete = true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we really default this to force delete? I suspect the safer option would be to not force delete by default? Especially since the bucket will contain flow logs, which would be needed for audit purposes. Perhaos it needs to be exposed, defaulted to false but set to true in all our tests (otherwise the destroy would fail)

}]
}

module "cos_buckets" {
count = var.enable_vpc_flow_logs ? 1 : 0
source = "terraform-ibm-modules/cos/ibm//modules/buckets"
version = "8.19.2"
bucket_configs = local.bucket_config
}

#######################################################################################################################
# KMS Key
#######################################################################################################################

# parse KMS details from the existing KMS instance CRN
module "existing_kms_instance_crn_parser" {
count = var.kms_encryption_enabled_bucket && var.existing_kms_instance_crn != null ? 1 : 0
source = "terraform-ibm-modules/common-utilities/ibm//modules/crn-parser"
version = "1.1.0"
crn = var.existing_kms_instance_crn
}

locals {
# fetch KMS region from existing_kms_instance_crn if KMS resources are required
kms_region = var.kms_encryption_enabled_bucket && var.existing_kms_instance_crn != null ? module.existing_kms_instance_crn_parser[0].region : null

kms_key_ring_name = try("${var.prefix}-${var.kms_key_ring_name}", var.kms_key_ring_name)
kms_key_name = try("${var.prefix}-${var.kms_key_name}", var.kms_key_name)

create_kms_key = var.existing_kms_key_crn == null ? ((var.enable_vpc_flow_logs && var.kms_encryption_enabled_bucket && var.existing_kms_instance_crn != null) ? true : false) : false
}

module "kms" {
count = local.create_kms_key ? 1 : 0 # no need to create any KMS resources if not passing an existing KMS CRN or existing KMS key CRN is provided
source = "terraform-ibm-modules/kms-all-inclusive/ibm"
version = "4.19.5"
create_key_protect_instance = false
region = local.kms_region
existing_kms_instance_crn = var.existing_kms_instance_crn
key_ring_endpoint_type = var.kms_endpoint_type
key_endpoint_type = var.kms_endpoint_type
keys = [
{
key_ring_name = local.kms_key_ring_name
existing_key_ring = false
force_delete_key_ring = true
keys = [
{
key_name = local.kms_key_name
standard_key = false
rotation_interval_month = 3
dual_auth_delete_enabled = false
force_delete = true
}
]
}
]
}

#############################################################################
# VPC
#############################################################################

locals {
# create 'use_public_gateways' object
public_gateway_object = {
for key, value in var.subnets : key => value != null ? length([for sub in value : sub.public_gateway if sub.public_gateway]) > 0 ? [for sub in value : sub.public_gateway if sub.public_gateway][0] : false : false
}
}

module "vpc" {
source = "../../"
resource_group_id = module.resource_group.resource_group_id
region = var.region
create_vpc = true
name = var.vpc_name
prefix = local.prefix
tags = var.resource_tags
access_tags = var.access_tags
subnets = var.subnets
default_network_acl_name = var.default_network_acl_name
default_security_group_name = var.default_security_group_name
default_routing_table_name = var.default_routing_table_name
network_acls = var.network_acls
clean_default_sg_acl = var.clean_default_sg_acl
use_public_gateways = local.public_gateway_object
address_prefixes = var.address_prefixes
routes = var.routes
enable_vpc_flow_logs = var.enable_vpc_flow_logs
create_authorization_policy_vpc_to_cos = !var.skip_vpc_cos_authorization_policy
existing_cos_instance_guid = var.enable_vpc_flow_logs ? module.existing_cos_crn_parser[0].service_instance : null
existing_storage_bucket_name = var.enable_vpc_flow_logs ? module.cos_buckets[0].buckets[0].bucket_name : null
enable_vpn_gateways = true
vpn_gateways = var.vpn_gateways
}
36 changes: 36 additions & 0 deletions solutions/fully-configurable/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
##############################################################################
# VPC
##############################################################################

output "vpc_name" {
description = "Name of VPC created"
value = module.vpc.vpc_name
}

output "vpc_id" {
description = "ID of VPC created"
value = module.vpc.vpc_id
}

output "vpc_crn" {
description = "CRN of VPC created"
value = module.vpc.vpc_crn
}

##############################################################################
# Public Gateways
##############################################################################

output "public_gateways" {
description = "Map of public gateways by zone"
value = module.vpc.public_gateways
}

##############################################################################
# VPC flow logs
##############################################################################

output "vpc_flow_logs" {
description = "Details of VPC flow logs collector"
value = module.vpc.vpc_flow_logs
}
9 changes: 9 additions & 0 deletions solutions/fully-configurable/provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
########################################################################################################################
# Provider config
########################################################################################################################

provider "ibm" {
ibmcloud_api_key = var.ibmcloud_api_key
region = var.region
visibility = var.provider_visibility
}
Loading