diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b8e3e6f --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# Global files to ignore in the project + +# macOS files to ignore +.DS_Store +._* + +# Visual Studio Code files to ignore +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace +.history/ + +# Node files to ignore +node_modules +bower_components +build/Release +web_modules/ +keys/ +.npm +*.tgz +.env +.env.test +.cache/ + +# Log files to ignore +logs +*.log* + +# Keys and Certificates files to ignore +*.crt +*.pem +*.key + +# Terraform files to ignore +**/.terraform/* +*.tf.bkp +*.tfstate +*.tfstate.* +*.auto.tfvars +*.lock.hcl +crash.log +test +terraform_key.json diff --git a/main.tf b/main.tf index a0a407d..786129a 100644 --- a/main.tf +++ b/main.tf @@ -1,10 +1,9 @@ - # provider block required with Schematics to set VPC region provider "ibm" { region = var.ibm_region #ibmcloud_api_key = var.ibmcloud_api_key - generation = local.generation - version = "~> 1.4" + # generation = local.generation + # version = "~> 1.4" } data "ibm_resource_group" "all_rg" { @@ -12,12 +11,12 @@ data "ibm_resource_group" "all_rg" { } locals { - generation = 2 + # generation = 2 frontend_count = 2 backend_count = 1 + datagov_count = 1 } - ################################################################################################## # Select CIDRs allowed to access bastion host # When running under Schematics allowed ingress CIDRs are set to only allow access from Schematics @@ -33,7 +32,7 @@ locals { geo = substr(local.region, 0, 2) schematics_ssh_access_map = { us = ["169.44.0.0/14", "169.60.0.0/14"], - eu = ["158.175.0.0/16","158.176.0.0/15","141.125.75.80/28","161.156.139.192/28","149.81.103.128/28"], + eu = ["158.175.0.0/16", "158.176.0.0/15", "141.125.75.80/28", "161.156.139.192/28", "149.81.103.128/28"], } schematics_ssh_access = lookup(local.schematics_ssh_access_map, local.geo, ["0.0.0.0/0"]) bastion_ingress_cidr = var.ssh_source_cidr_override[0] != "0.0.0.0/0" ? var.ssh_source_cidr_override : local.schematics_ssh_access @@ -41,27 +40,30 @@ locals { module "vpc" { - source = "./vpc" - ibm_region = var.ibm_region - resource_group_name = var.resource_group_name - generation = local.generation + source = "./vpc" + ibm_region = var.ibm_region + resource_group_name = var.resource_group_name + # generation = local.generation unique_id = var.vpc_name frontend_count = local.frontend_count frontend_cidr_blocks = local.frontend_cidr_blocks backend_count = local.backend_count backend_cidr_blocks = local.backend_cidr_blocks + datagov_count = local.datagov_count + datagov_cidr_blocks = local.datagov_cidr_blocks } locals { # bastion_cidr_blocks = [cidrsubnet(var.bastion_cidr, 4, 0), cidrsubnet(var.bastion_cidr, 4, 2), cidrsubnet(var.bastion_cidr, 4, 4)] frontend_cidr_blocks = [cidrsubnet(var.frontend_cidr, 4, 0), cidrsubnet(var.frontend_cidr, 4, 2), cidrsubnet(var.frontend_cidr, 4, 4)] backend_cidr_blocks = [cidrsubnet(var.backend_cidr, 4, 0), cidrsubnet(var.backend_cidr, 4, 2), cidrsubnet(var.backend_cidr, 4, 4)] + datagov_cidr_blocks = [cidrsubnet(var.datagov_cidr, 4, 0), cidrsubnet(var.datagov_cidr, 4, 2), cidrsubnet(var.datagov_cidr, 4, 4)] } # Create single zone bastion module "bastion" { - source = "./bastionmodule" + source = "./modules/bastion" ibm_region = var.ibm_region bastion_count = 1 unique_id = var.vpc_name @@ -69,18 +71,14 @@ module "bastion" { ibm_is_resource_group_id = data.ibm_resource_group.all_rg.id bastion_cidr = var.bastion_cidr ssh_source_cidr_blocks = local.bastion_ingress_cidr - destination_cidr_blocks = [var.frontend_cidr, var.backend_cidr] - destination_sgs = [module.frontend.security_group_id, module.backend.security_group_id] - # destination_sg = [module.frontend.security_group_id, module.backend.security_group_id] - # vsi_profile = "cx2-2x4" - # image_name = "ibm-centos-7-6-minimal-amd64-1" + destination_cidr_blocks = [var.frontend_cidr, var.backend_cidr, var.datagov_cidr] + destination_sgs = [module.frontend.security_group_id, module.backend.security_group_id, module.datagov.security_group_id] ssh_key_id = data.ibm_is_ssh_key.sshkey.id } - module "frontend" { - source = "./frontendmodule" + source = "./modules/frontend" ibm_region = var.ibm_region unique_id = var.vpc_name ibm_is_vpc_id = module.vpc.vpc_id @@ -92,12 +90,13 @@ module "frontend" { subnet_ids = module.vpc.frontend_subnet_ids bastion_remote_sg_id = module.bastion.security_group_id bastion_subnet_CIDR = var.bastion_cidr - pub_repo_egress_cidr = local.pub_repo_egress_cidr app_backend_sg_id = module.backend.security_group_id + app_datagov_sg_id = module.datagov.security_group_id + pub_repo_egress_cidr = local.pub_repo_egress_cidr } module "backend" { - source = "./backendmodule" + source = "./modules/backend" ibm_region = var.ibm_region unique_id = var.vpc_name ibm_is_vpc_id = module.vpc.vpc_id @@ -110,13 +109,32 @@ module "backend" { bastion_remote_sg_id = module.bastion.security_group_id bastion_subnet_CIDR = var.bastion_cidr app_frontend_sg_id = module.frontend.security_group_id + app_datagov_sg_id = module.datagov.security_group_id + pub_repo_egress_cidr = local.pub_repo_egress_cidr +} + +module "datagov" { + source = "./modules/datagovernance" + ibm_region = var.ibm_region + unique_id = var.vpc_name + ibm_is_vpc_id = module.vpc.vpc_id + ibm_is_resource_group_id = data.ibm_resource_group.all_rg.id + datagov_count = local.datagov_count + profile = var.profile + ibm_is_image_id = data.ibm_is_image.os.id + ibm_is_ssh_key_id = data.ibm_is_ssh_key.sshkey.id + subnet_ids = module.vpc.datagov_subnet_ids + bastion_remote_sg_id = module.bastion.security_group_id + bastion_subnet_CIDR = var.bastion_cidr + app_frontend_sg_id = module.frontend.security_group_id + app_backend_sg_id = module.backend.security_group_id pub_repo_egress_cidr = local.pub_repo_egress_cidr } module "accesscheck" { - source = "./accesscheck" + source = "./modules/accesscheck" ssh_accesscheck = var.ssh_accesscheck ssh_private_key = var.ssh_private_key bastion_host = module.bastion.bastion_ip_addresses[0] - target_hosts = concat(module.frontend.primary_ipv4_address, module.backend.primary_ipv4_address) + target_hosts = concat(module.frontend.primary_ipv4_address, module.backend.primary_ipv4_address, module.datagov.primary_ipv4_address) } diff --git a/accesscheck/main.tf b/modules/accesscheck/main.tf similarity index 100% rename from accesscheck/main.tf rename to modules/accesscheck/main.tf diff --git a/accesscheck/outputs.tf b/modules/accesscheck/outputs.tf similarity index 100% rename from accesscheck/outputs.tf rename to modules/accesscheck/outputs.tf diff --git a/accesscheck/vars.tf b/modules/accesscheck/vars.tf similarity index 100% rename from accesscheck/vars.tf rename to modules/accesscheck/vars.tf diff --git a/modules/accesscheck/versions.tf b/modules/accesscheck/versions.tf new file mode 100644 index 0000000..ff9ba3f --- /dev/null +++ b/modules/accesscheck/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_providers { + ibm = { + source = "ibm-cloud/ibm" + version = "1.30.0" + } + } +} + diff --git a/backendmodule/back_nacl.tf b/modules/backend/back_nacl.tf similarity index 100% rename from backendmodule/back_nacl.tf rename to modules/backend/back_nacl.tf diff --git a/backendmodule/cloudinit.tf b/modules/backend/cloudinit.tf similarity index 100% rename from backendmodule/cloudinit.tf rename to modules/backend/cloudinit.tf diff --git a/backendmodule/main.tf b/modules/backend/main.tf similarity index 97% rename from backendmodule/main.tf rename to modules/backend/main.tf index 4756fc5..5ba93d5 100644 --- a/backendmodule/main.tf +++ b/modules/backend/main.tf @@ -96,6 +96,8 @@ locals { sg_rules = [ ["inbound", var.bastion_remote_sg_id, "tcp", 22, 22], ["inbound", var.app_frontend_sg_id, "tcp", 27017, 27017], + ["inbound", var.app_datagov_sg_id, "tcp", 27017, 27017], + ["outbound", var.app_datagov_sg_id, "tcp", 9300, 9300], ["outbound", "161.26.0.0/24", "tcp", 443, 443], ["outbound", "161.26.0.0/24", "tcp", 80, 80], ["outbound", "161.26.0.0/24", "udp", 53, 53], diff --git a/backendmodule/outputs.tf b/modules/backend/outputs.tf similarity index 100% rename from backendmodule/outputs.tf rename to modules/backend/outputs.tf diff --git a/backendmodule/vars.tf b/modules/backend/vars.tf similarity index 96% rename from backendmodule/vars.tf rename to modules/backend/vars.tf index ef2c1db..e65456c 100644 --- a/backendmodule/vars.tf +++ b/modules/backend/vars.tf @@ -33,6 +33,9 @@ variable "subnet_ids" { variable "app_frontend_sg_id" { } +variable "app_datagov_sg_id" { +} + # bastion sg requiring access to backend security group variable "bastion_remote_sg_id" { } diff --git a/modules/backend/versions.tf b/modules/backend/versions.tf new file mode 100644 index 0000000..ff9ba3f --- /dev/null +++ b/modules/backend/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_providers { + ibm = { + source = "ibm-cloud/ibm" + version = "1.30.0" + } + } +} + diff --git a/bastionmodule/bast_nacl.tf b/modules/bastion/bast_nacl.tf similarity index 100% rename from bastionmodule/bast_nacl.tf rename to modules/bastion/bast_nacl.tf diff --git a/bastionmodule/bast_sg.tf b/modules/bastion/bast_sg.tf similarity index 100% rename from bastionmodule/bast_sg.tf rename to modules/bastion/bast_sg.tf diff --git a/bastionmodule/bastion.tf b/modules/bastion/bastion.tf similarity index 100% rename from bastionmodule/bastion.tf rename to modules/bastion/bastion.tf diff --git a/bastionmodule/bastion_config.yml b/modules/bastion/bastion_config.yml similarity index 100% rename from bastionmodule/bastion_config.yml rename to modules/bastion/bastion_config.yml diff --git a/bastionmodule/outputs.tf b/modules/bastion/outputs.tf similarity index 100% rename from bastionmodule/outputs.tf rename to modules/bastion/outputs.tf diff --git a/bastionmodule/vars.tf b/modules/bastion/vars.tf similarity index 100% rename from bastionmodule/vars.tf rename to modules/bastion/vars.tf diff --git a/modules/bastion/versions.tf b/modules/bastion/versions.tf new file mode 100644 index 0000000..ff9ba3f --- /dev/null +++ b/modules/bastion/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_providers { + ibm = { + source = "ibm-cloud/ibm" + version = "1.30.0" + } + } +} + diff --git a/modules/create_services/main.tf b/modules/create_services/main.tf new file mode 100644 index 0000000..4c2a3ac --- /dev/null +++ b/modules/create_services/main.tf @@ -0,0 +1,142 @@ +# Cloud logging +resource "ibm_resource_instance" "logging" { + count = var.create_logging ? 1 : 0 + name = "${var.basename}-logging" + resource_group_id = var.resource_group_id + service = "logdna" + plan = "7-day" + location = var.region + tags = concat(var.tags, ["service"]) +} + +resource "ibm_resource_key" "logging_key" { + count = var.create_logging ? 1 : 0 + name = "${var.basename}-logging-key" + resource_instance_id = ibm_resource_instance.logging.0.id + role = "Manager" +} + +# Cloud monitoring +resource "ibm_resource_instance" "monitoring" { + count = var.create_monitoring ? 1 : 0 + name = "${var.basename}-monitoring" + resource_group_id = var.resource_group_id + service = "sysdig-monitor" + plan = "graduated-tier" + location = var.region + tags = concat(var.tags, ["service"]) +} + +resource "ibm_resource_key" "monitoring_key" { + count = var.create_monitoring ? 1 : 0 + name = "${var.basename}-monitoring-key" + resource_instance_id = ibm_resource_instance.monitoring.0.id + role = "Manager" +} + +# Create Key protect + root key +resource "ibm_resource_instance" "keyprotect" { + + name = "${var.basename}-kms" + resource_group_id = var.resource_group_id + service = "kms" + plan = "tiered-pricing" + location = var.region + tags = concat(var.tags, ["service"]) + service_endpoints = "private" +} + +resource "ibm_kms_key" "key" { + instance_id = ibm_resource_instance.keyprotect.guid + key_name = "root_key" + standard_key = false + force_delete = true +} + +# Create Cloud Object Storage service, policy and COS bucket + +resource "ibm_resource_instance" "cos" { + + name = "${var.basename}-cos" + resource_group_id = var.resource_group_id + service = "cloud-object-storage" + plan = "standard" + location = "global" + tags = concat(var.tags, ["service"]) + service_endpoints = "private" +} + +resource "ibm_resource_key" "cos_key" { + + name = "${var.basename}-cos-key" + resource_instance_id = ibm_resource_instance.cos.id + role = "Writer" + + parameters = { + service-endpoints = "private" + HMAC = true + } + depends_on = [ibm_iam_authorization_policy.cos_policy] +} + +resource "ibm_iam_authorization_policy" "cos_policy" { + source_service_name = "cloud-object-storage" + source_resource_instance_id = ibm_resource_instance.cos.guid + target_service_name = ibm_kms_key.key.type + target_resource_instance_id = ibm_resource_instance.keyprotect.guid + roles = ["Reader"] +} + +resource "random_uuid" "uuid" { +} + +resource "ibm_cos_bucket" "bucket" { + bucket_name = "${var.basename}-${random_uuid.uuid.result}-bucket" + key_protect = ibm_kms_key.key.crn + resource_instance_id = ibm_resource_instance.cos.id + region_location = var.region + storage_class = "smart" + force_delete = true + depends_on = [ibm_iam_authorization_policy.cos_policy] +} + +# Create a Postgresql DB + +resource "ibm_database" "postgresql" { + resource_group_id = var.resource_group_id + name = "${var.basename}-postgres" + service = "databases-for-postgresql" + plan = "standard" + location = var.region + tags = concat(var.tags, ["service"]) + key_protect_key = ibm_kms_key.key.crn + service_endpoints = "private" + depends_on = [ibm_iam_authorization_policy.postgresql_policy] +} + +resource "ibm_resource_key" "postgresql_key" { + name = "${var.basename}-postgresql-key" + resource_instance_id = ibm_database.postgresql.id + role = "Administrator" + + parameters = { + service-endpoints = "private" + } + depends_on = [ibm_iam_authorization_policy.postgresql_policy] +} + +resource "ibm_iam_authorization_policy" "postgresql_policy" { + source_service_name = "databases-for-postgresql" + target_service_name = ibm_kms_key.key.type + target_resource_instance_id = ibm_resource_instance.keyprotect.guid + roles = ["Reader", "AuthorizationDelegator"] +} + +resource "time_sleep" "wait_for_postgresql_initialization" { + #count = var.step2_create_vpc || var.step4_create_dedicated ? 1 : 0 + depends_on = [ + ibm_database.postgresql + ] + + create_duration = "5m" +} \ No newline at end of file diff --git a/modules/create_services/outputs.tf b/modules/create_services/outputs.tf new file mode 100644 index 0000000..8e2e57e --- /dev/null +++ b/modules/create_services/outputs.tf @@ -0,0 +1,42 @@ +output "keyprotect_guid" { + value = ibm_resource_instance.keyprotect.guid +} + +output "keyprotect_key_type" { + value = ibm_kms_key.key.type +} + +output "keyprotect_key_id" { + value = ibm_kms_key.key.id +} + +output "keyprotect_crn" { + value = ibm_resource_instance.keyprotect.target_crn +} + +output "cos_crn" { + value = ibm_resource_instance.cos.target_crn +} + +output "cos_key" { + value = ibm_resource_key.cos_key + sensitive = true +} + +output "postgresql" { + value = ibm_database.postgresql + sensitive = true +} + +output "postgresql_crn" { + value = ibm_database.postgresql.id +} + +output "postgresql_key" { + value = ibm_resource_key.postgresql_key + sensitive = true +} + +output "bucket_name" { + value = ibm_cos_bucket.bucket.bucket_name +} \ No newline at end of file diff --git a/modules/create_services/variables.tf b/modules/create_services/variables.tf new file mode 100644 index 0000000..de9021d --- /dev/null +++ b/modules/create_services/variables.tf @@ -0,0 +1,28 @@ +variable "basename" { + type = string +} + +variable "region" { + type = string + default = "us-south" +} + +variable "resource_group_id" { + type = string +} + +variable "tags" { + type = list(string) +} + +variable "create_logging" { + type = bool + default = false + description = "Create a logging instance in the region and resource group provided above" +} + +variable "create_monitoring" { + type = bool + default = false + description = "Create a monitoring instance in the region and resource group provided above" +} \ No newline at end of file diff --git a/modules/create_services/versions.tf b/modules/create_services/versions.tf new file mode 100644 index 0000000..38fd583 --- /dev/null +++ b/modules/create_services/versions.tf @@ -0,0 +1,7 @@ +terraform { + required_providers { + ibm = { + source = "IBM-Cloud/ibm" + } + } +} diff --git a/modules/create_vpe/main.tf b/modules/create_vpe/main.tf new file mode 100644 index 0000000..a88af5d --- /dev/null +++ b/modules/create_vpe/main.tf @@ -0,0 +1,23 @@ +resource "ibm_is_virtual_endpoint_gateway" "vpe" { + for_each = { for target in var.endpoints : target.name => target } + + name = "${var.basename}-${each.key}-vpe" + resource_group = var.resource_group_id + vpc = var.vpc_id + + target { + crn = each.value.crn + resource_type = "provider_cloud_service" + } + + # one Reserved IP for per zone in the VPC + dynamic "ips" { + for_each = { for subnet in var.subnets : subnet.id => subnet } + content { + subnet = ips.key + name = "${ips.value.name}-${each.key}-ip" + } + } + + tags = var.tags +} \ No newline at end of file diff --git a/modules/create_vpe/variables.tf b/modules/create_vpe/variables.tf new file mode 100644 index 0000000..a712461 --- /dev/null +++ b/modules/create_vpe/variables.tf @@ -0,0 +1,28 @@ +variable "basename" { + type = string +} + +variable "region" { + type = string +} + +variable "resource_group_id" { + type = string +} + +variable "vpc_id" { + type = string +} + +variable "endpoints" { + type = any +} + +variable "subnets" { + type = any +} + +variable "tags" { + type = list(string) + default = ["terraform", "vpc-scaling"] +} diff --git a/modules/create_vpe/versions.tf b/modules/create_vpe/versions.tf new file mode 100644 index 0000000..38fd583 --- /dev/null +++ b/modules/create_vpe/versions.tf @@ -0,0 +1,7 @@ +terraform { + required_providers { + ibm = { + source = "IBM-Cloud/ibm" + } + } +} diff --git a/frontendmodule/cloudinit.tf b/modules/datagovernance/cloudinit.tf similarity index 100% rename from frontendmodule/cloudinit.tf rename to modules/datagovernance/cloudinit.tf diff --git a/modules/datagovernance/data_nacl.tf b/modules/datagovernance/data_nacl.tf new file mode 100644 index 0000000..67d527b --- /dev/null +++ b/modules/datagovernance/data_nacl.tf @@ -0,0 +1,10 @@ + +############################################################################## +# Config to dynamically create backend host Network ACL and rules +# +# Base rules for access to DNS, repos are predefined. Inputs required for +# source subnets backend VSIs host will be connected to by the front end VSIs and +# bastion host +############################################################################## + +# placeholder diff --git a/modules/datagovernance/main.tf b/modules/datagovernance/main.tf new file mode 100644 index 0000000..d00d5f2 --- /dev/null +++ b/modules/datagovernance/main.tf @@ -0,0 +1,161 @@ +###################################################################################### +# Sample module to deploy a 'data governance' webserver VSI and security group +# No NACL is defined. As no floating (public) IPs are defined, the Security Group +# configuration by itself is considered sufficient to protect access to the VSIs. +# Subnet is created in VPC module. +# +# Redhat Ansible usage is enabled by the addition of VSI tags. All Ansible related VSI +# tags are prefixed with "ans_group:" followed by the group name. ' +# tags = ["ans_group:datagov"]' +# Correct specification of tags is essential for operation of the Ansible dynamic inventory +# script used to pass host information to Ansible. The tags here should match the roles +# defined in the site.yml playbook file. +####################################################################################### + + +resource "ibm_is_instance" "datagov-server" { + count = var.datagov_count + name = "${var.unique_id}-datagov-vsi-${count.index + 1}" + image = var.ibm_is_image_id + profile = var.profile + + primary_network_interface { + subnet = var.subnet_ids[count.index] + security_groups = [ibm_is_security_group.datagov.id] + } + + vpc = var.ibm_is_vpc_id + zone = "${var.ibm_region}-${count.index % 3 + 1}" + resource_group = var.ibm_is_resource_group_id + keys = [var.ibm_is_ssh_key_id] + user_data = data.template_cloudinit_config.app_userdata.rendered + tags = ["schematics:group:datagov"] +} + + +############################################################################## +# Private load balancer +# +############################################################################## + + +# resource "ibm_is_lb" "webapptier-lb" { +# name = "datagovtier" +# type = "private" +# subnets = toset(var.subnet_ids) +# resource_group = var.ibm_is_resource_group_id +# } + + +# resource "ibm_is_lb_listener" "webapptier-lb-listener" { +# lb = ibm_is_lb.webapptier-lb.id +# port = "80" +# protocol = "http" +# default_pool = element(split("/", ibm_is_lb_pool.webapptier-lb-pool.id), 1) +# depends_on = [ibm_is_lb_pool.webapptier-lb-pool] +# } + +# resource "ibm_is_lb_pool" "webapptier-lb-pool" { +# lb = ibm_is_lb.webapptier-lb.id +# name = "webapptier-lb-pool" +# protocol = "http" +# algorithm = "round_robin" +# health_delay = "5" +# health_retries = "2" +# health_timeout = "2" +# health_type = "http" +# health_monitor_url = "/" +# depends_on = [ibm_is_lb.webapptier-lb] +# } + +# resource "ibm_is_lb_pool_member" "webapptier-lb-pool-member-zone1" { +# count = var.datagov_count +# lb = ibm_is_lb.webapptier-lb.id +# pool = element(split("/", ibm_is_lb_pool.webapptier-lb-pool.id), 1) +# port = "8080" +# target_address = ibm_is_instance.datagov-server[count.index].primary_network_interface[0].primary_ipv4_address +# depends_on = [ibm_is_lb_pool.webapptier-lb-pool] +# } + + + + + +# this is the SG applied to the data governance instances +resource "ibm_is_security_group" "datagov" { + name = "${var.unique_id}-datagov-sg" + vpc = var.ibm_is_vpc_id + resource_group = var.ibm_is_resource_group_id +} + + +locals { + sg_keys = ["direction", "remote", "type", "port_min", "port_max"] + + + sg_rules = [ + ["inbound", var.bastion_remote_sg_id, "tcp", 22, 22], + ["inbound", var.app_backend_sg_id, "tcp", 9300, 9300], + ["inbound", var.app_frontend_sg_id, "tcp", 9300, 9300], + ["outbound", var.app_backend_sg_id, "tcp", 27017, 27017], + ["outbound", "161.26.0.0/24", "tcp", 443, 443], + ["outbound", "161.26.0.0/24", "tcp", 80, 80], + ["outbound", "161.26.0.0/24", "udp", 53, 53], + ["outbound", var.pub_repo_egress_cidr, "tcp", 443, 443], + ["inbound", "0.0.0.0/0", "tcp", 80, 80] + ] + + sg_mappedrules = [ + for entry in local.sg_rules : + merge(zipmap(local.sg_keys, entry)) + ] +} + + +resource "ibm_is_security_group_rule" "datagov_access" { + count = length(local.sg_mappedrules) + group = ibm_is_security_group.datagov.id + direction = (local.sg_mappedrules[count.index]).direction + remote = (local.sg_mappedrules[count.index]).remote + dynamic "tcp" { + for_each = local.sg_mappedrules[count.index].type == "tcp" ? [ + { + port_max = local.sg_mappedrules[count.index].port_max + port_min = local.sg_mappedrules[count.index].port_min + } + ] : [] + content { + port_max = tcp.value.port_max + port_min = tcp.value.port_min + + } + } + dynamic "udp" { + for_each = local.sg_mappedrules[count.index].type == "udp" ? [ + { + port_max = local.sg_mappedrules[count.index].port_max + port_min = local.sg_mappedrules[count.index].port_min + } + ] : [] + content { + port_max = udp.value.port_max + port_min = udp.value.port_min + } + } + dynamic "icmp" { + for_each = local.sg_mappedrules[count.index].type == "icmp" ? [ + { + type = local.sg_mappedrules[count.index].port_max + code = local.sg_mappedrules[count.index].port_min + } + ] : [] + content { + type = icmp.value.type + code = icmp.value.code + } + } +} + + + + diff --git a/modules/datagovernance/outputs.tf b/modules/datagovernance/outputs.tf new file mode 100644 index 0000000..c6e5229 --- /dev/null +++ b/modules/datagovernance/outputs.tf @@ -0,0 +1,8 @@ + +output security_group_id { + value = ibm_is_security_group.datagov.id +} + +output primary_ipv4_address { + value = ibm_is_instance.datagov-server[*].primary_network_interface[0].primary_ipv4_address +} diff --git a/modules/datagovernance/vars.tf b/modules/datagovernance/vars.tf new file mode 100644 index 0000000..11fc17a --- /dev/null +++ b/modules/datagovernance/vars.tf @@ -0,0 +1,54 @@ +variable "unique_id" { +} # string added to the front for all created resources + +# create resources in this vpc id +variable "ibm_is_vpc_id" { +} + +# create resources in this resource group id +variable "ibm_is_resource_group_id" { +} + +variable "ibm_region" { + description = "IBM Cloud region where all resources will be deployed" + default = "us-south" +} + +# VSI compute profile for webserver host +variable "profile" { +} + +# Id of VSI image +variable "ibm_is_image_id" { +} + +# SSH key for data governance webservers. +variable "ibm_is_ssh_key_id" { +} + +# webserver instance is put in this subnet +variable "subnet_ids" { +} + +variable "app_frontend_sg_id" { +} + +variable "app_backend_sg_id" { +} + +# bastion sg requiring access to data governance security group +variable "bastion_remote_sg_id" { +} + +# bastion subnet CIDR requiring access to data governance subnets +variable "bastion_subnet_CIDR" { +} + +# Allowable CIDRs of public repos from which Ansible can deploy code +variable "pub_repo_egress_cidr" { +} + +variable "datagov_count" { + description = "number of data governance zones" + default = 1 +} diff --git a/modules/datagovernance/versions.tf b/modules/datagovernance/versions.tf new file mode 100644 index 0000000..ff9ba3f --- /dev/null +++ b/modules/datagovernance/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_providers { + ibm = { + source = "ibm-cloud/ibm" + version = "1.30.0" + } + } +} + diff --git a/modules/flowlogs/flowlog.tf b/modules/flowlogs/flowlog.tf new file mode 100755 index 0000000..1f7d8f7 --- /dev/null +++ b/modules/flowlogs/flowlog.tf @@ -0,0 +1,32 @@ +############################################################################## +# This file creates flow log for any given resource. +# All logs are assumed to go in the same global cos instance. In case aother +# instance is supposed to be used +############################################################################## + +# Instance Details +resource "ibm_resource_instance" "flowlog_cos_instance" { + name = "flowlog-cos-instance" + resource_group_id = var.ibm_is_resource_group_id + service = "cloud-object-storage" + plan = var.ibm_res_cos_plan + location = "global" +} + +# Bucket specific to the resource +resource "ibm_cos_bucket" "cos_bucket" { + bucket_name = "${var.unique_id}-cos-flowlog" + resource_instance_id = ibm_resource_instance.flowlog_cos_instance.id + storage_class = var.ibm_res_cos_plan + region_location = var.ibm_region +} + +# There are flow logs that may or may not need dependency check +resource "ibm_is_flow_log" "res_flowlog" { + # check if there is dependency + # depends_on = ibm_is_vpc.VPC + name = "${var.unique_id}-flow-log" + target = var.ibm_is_res_target_id + # active = true + storage_bucket = ibm_cos_bucket.cos_bucket.bucket_name +} diff --git a/modules/flowlogs/vars.tf b/modules/flowlogs/vars.tf new file mode 100644 index 0000000..31ad528 --- /dev/null +++ b/modules/flowlogs/vars.tf @@ -0,0 +1,27 @@ +variable "unique_id" { +} # string added to the front for all created resources + +variable "ibm_region" { + description = "IBM Cloud region where all resources will be deployed" + default = "us-south" +} + +# create resources in this vpc id +variable "ibm_is_vpc_id" { +} + +# create resources in this resource group id +variable "ibm_is_resource_group_id" { +} + +# Target is an instance, subnet, or VPC, flow logs is not collected for any network +# interfaces within the target that are more specific flow log collector. +variable "ibm_is_res_target_id" { + description = "The ID of the target to collect flow logs" +} + +# COS Plan selected for Flow Logs +variable "ibm_res_cos_plan" { + description = "Default plan for IBM Cloud Object Storage" + default = "standard" +} \ No newline at end of file diff --git a/modules/flowlogs/versions.tf b/modules/flowlogs/versions.tf new file mode 100644 index 0000000..dc4c823 --- /dev/null +++ b/modules/flowlogs/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_providers { + ibm = { + source = "ibm-cloud/ibm" + version = "1.30.0" + } + } +} + diff --git a/modules/frontend/cloudinit.tf b/modules/frontend/cloudinit.tf new file mode 100644 index 0000000..0d0025c --- /dev/null +++ b/modules/frontend/cloudinit.tf @@ -0,0 +1,19 @@ +data "template_cloudinit_config" "app_userdata" { + base64_encode = false + gzip = false + + part { + content = <