diff --git a/concourse/pipelines/create-cloudfoundry.yml b/concourse/pipelines/create-cloudfoundry.yml index 485407ac0f..bcd95e93cc 100644 --- a/concourse/pipelines/create-cloudfoundry.yml +++ b/concourse/pipelines/create-cloudfoundry.yml @@ -4246,6 +4246,7 @@ jobs: cf auth "${CF_ADMIN}" "${CF_PASS}" ./paas-cf/concourse/scripts/set_security_groups_from_manifest.rb cf-manifest/cf-manifest.yml + ./paas-cf/concourse/scripts/apply_security_group_bindings_from_vpc_peering_json.rb "./paas-cf/terraform/((deploy_env)).vpc_peering.json" # TODO Remove below after 09/03/2023. This is not needed after it has been run once in each environment. cf delete-security-group secret_manager_endpoint -f || true diff --git a/concourse/scripts/apply_security_group_bindings_from_vpc_peering_json.rb b/concourse/scripts/apply_security_group_bindings_from_vpc_peering_json.rb new file mode 100755 index 0000000000..c337cf8461 --- /dev/null +++ b/concourse/scripts/apply_security_group_bindings_from_vpc_peering_json.rb @@ -0,0 +1,72 @@ +#!/usr/bin/env ruby + +require "json" + +if ARGV.empty? || !File.file?(ARGV[0]) + abort "Usage: #{$PROGRAM_NAME} /path/to/env_vpc_peering_file.json [--dry-run]" +end + +if ARGV[1] == "--dry-run" + dry_run = true +end + +config_data = File.read(ARGV[0]) + +begin + config = JSON.parse(config_data) +rescue JSON::ParserError => e + abort "Error parsing JSON file: #{e.message}" +end + +config.each_with_index do |peer, peer_index| + peer_name = peer["peer_name"] + bindings = peer["bindings"] + if peer_name.nil? || peer_name.empty? + puts "Error in JSON data at peer index #{peer_index}: Missing 'peer_name'." + exit(1) + end + if bindings.nil? || bindings.empty? + puts "Skipping at peer index #{peer_index}: Missing 'bindings'." + next + end + sec_group_name = "vpc_peer_#{peer_name}" + bindings&.each do |binding| + org_name = binding["org_name"] + all_spaces = binding["all_spaces"] + spaces = binding["spaces"] + if org_name.nil? || org_name.empty? + puts "Error in JSON data at peer index #{peer_index}: Missing 'org_name' in bindings." + next + exit(1) + end + if all_spaces == true + command = "cf bind-security-group #{sec_group_name} #{org_name}" + if dry_run + puts "dry-run: #{command}" + else + success = system(command) + unless success + puts "Error executing command: #{command}" + exit(1) + end + end + else + if spaces.nil? || spaces.empty? + puts "Error in JSON data at peer index #{peer_index}: Missing 'spaces' key when 'all_spaces' is false." + next + end + spaces&.each do |space| + command = "cf bind-security-group #{sec_group_name} #{org_name} --space #{space}" + if dry_run + puts "dry-run: #{command}" + else + success = system(command) + unless success + puts "Error executing command: #{command}" + exit(1) + end + end + end + end + end +end diff --git a/terraform/env.vpc_peering.json.example b/terraform/env.vpc_peering.json.example new file mode 100644 index 0000000000..58bde96832 --- /dev/null +++ b/terraform/env.vpc_peering.json.example @@ -0,0 +1,42 @@ +[ + { + "peer_name": "testing-01", + "account_id": "595665891067", + "vpc_id": "vpc-09fd619806a886763", + "subnet_cidr": "172.44.0.0/22", + "backing_service_routing": false, + "bindings": [ + { + "org_name": "admin", + "spaces": [ + "billing" + ] + } + ] + }, + { + "peer_name": "testing-02", + "account_id": "595665891067", + "vpc_id": "vpc-051e9bb3453774fae", + "subnet_cidr": "172.48.0.0/22", + "backing_service_routing": false, + "bindings": [ + { + "org_name": "admin", + "all_spaces": false, + "spaces": [ + "billing", + "healthchecks" + ] + }, + { + "org_name": "govuk-paas", + "all_spaces": false, + "spaces": [ + "docs", + "tools" + ] + } + ] + } +] diff --git a/terraform/vpc-peering/variables.tf b/terraform/vpc-peering/variables.tf index e71dce843c..f6d412a09d 100644 --- a/terraform/vpc-peering/variables.tf +++ b/terraform/vpc-peering/variables.tf @@ -1,14 +1,19 @@ variable "vpc_peers" { type = list(object({ - peer_name = string - account_id = string - vpc_id = string + peer_name = string + account_id = string + vpc_id = string subnet_cidr = string backing_service_routing = optional(bool) + bindings = optional(list(object({ + org_name = string + all_spaces = optional(bool) + spaces = optional(list(string)) + }))) })) default = [] validation { - condition = alltrue([for peer in var.vpc_peers : length(regexall("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(3[0-2]|[1-2][0-9]|[0-9]))$", peer.subnet_cidr)) > 0]) + condition = alltrue([for peer in var.vpc_peers : length(regexall("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/(3[0-2]|[1-2][0-9]|[0-9]))$", peer.subnet_cidr)) > 0]) error_message = "A valid CIDR range is required." } }