Terraform AWS VCPe Route Creation Endpoint Not Found - amazon-web-services

When I create a route to an endpoint I get the following error:
InvalidVpcEndpointId.NotFound: The vpcEndpoint ID 'vpce-044e0beXXXXXXXX' does not exist.
But further up in the output (and on the console) I can see the endpoint is created:
module.sec.aws_vpc_endpoint.s3[0]: Creation complete after 6s [id=vpce-044e0beXXXXXXXXX]
This is what I have to create the route:
resource "aws_route" "s3_route" {
count = length(var.s3_routes)
route_table_id = aws_route_table.main.id
destination_cidr_block = var.s3_routes[count.index]
vpc_endpoint_id = var.s3_endpoint_ID[0]
}
This module is an example of one that calls it:
module "sec-route-NATGW-ifw-a" {
source = "./route"
depends_on = [module.i-dmz, module.t-dmz, module.cde, module.tgw-core, module.tgw-ifw]
vpc_id = module.sec.vpc_id
subnet_association = [for s in range(0, length(module.sec.natgw_subnet_IDs)) : module.sec.natgw_subnet_IDs[s] if module.sec.natgw_subnet_AZs[s] == "${local.region}a"]
s3_endpoint_ID = module.sec.s3_endpoint_ID
s3_routes = local.s3_ips
}
And this is the output for the ID:
output "s3_endpoint_ID" {
value = aws_vpc_endpoint.s3[*].id
description = "ID for S3 Endpoint"
}
And the resource to create the endpoint:
resource "aws_vpc_endpoint" "s3" {
count = var.s3_servicename == "" ? 0 : 1
vpc_id = aws_vpc.SEC.id
service_name = var.s3_servicename
}
FYI VPCE ID has been changed from script.

The issue was the configuration on my route resource, I replaced it with the following:
resource "aws_vpc_endpoint_route_table_association" "s3" {
count = length(var.s3_endpoint_ID) == 0 ? 0 : 1
route_table_id = aws_route_table.main.id
vpc_endpoint_id = tostring(var.s3_endpoint_ID[0])
}
I don't think the tostring() is needed and I changed how count worked slightly, but adding the destination_cidr_block argument was the issue.

Related

Terraform ENI Mapping error - does not fall within the subnet's address range

I am trying to map my ENI to my subnet and its throwing an error.
Because there is a for_each loop on the subnet the ENI pointing to it must also have a looped key/value added to it hence the problem
main.tf
# VPC
resource "aws_vpc" "main" {
cidr_block = local.json.vpc.cidr
tags = {
Name = "vpc"
}
}
# Subnet
resource "aws_subnet" "public" {
for_each = local.api
vpc_id = aws_vpc.main.id
cidr_block = each.value.subnet_cidr
availability_zone = each.value.subnet_az
}
# ENI
resource "aws_network_interface" "eni" {
for_each = local.api
subnet_id = aws_subnet.public[each.key].id
private_ips = ["172.16.10.100"] # Might need to add another IP
tags = {
Name = "primary_network_interface"
}
}
my locals look like this
locals {
json = jsondecode(file("API.json"))
api = merge([
for vpc in local.json : {
for subnet in vpc.subnets :
"${vpc.name}-${subnet.name}" => {
vpc_name = vpc.name
vpc_cidr = vpc.cidr
subnet_name = subnet.name
subnet_cidr = subnet.cidr
subnet_az = subnet.az
}
}
]...)
}
their output (local.api) from terraform console
{
"vpc-subnet-one" = {
"subnet_az" = "eu-central-1a"
"subnet_cidr" = "192.168.1.0/24"
"subnet_name" = "subnet-one"
"vpc_cidr" = "192.168.0.0/16"
"vpc_name" = "vpc"
}
"vpc-subnet-two" = {
"subnet_az" = "eu-central-1b"
"subnet_cidr" = "192.168.4.0/24"
"subnet_name" = "subnet-two"
"vpc_cidr" = "192.168.0.0/16"
"vpc_name" = "vpc"
}
}
error message
status code: 400, request id: 64e031e5-11ea-4f6d-a03c-9a36a1ff56af
with aws_network_interface.eni["vpc-subnet-one"],
on main.tf line 20, in resource "aws_network_interface" "eni":
20: resource "aws_network_interface" "eni" {
Error: creating EC2 Network Interface: InvalidParameterValue: Address does not fall within the subnet's address range
status code: 400, request id: 7842f089-08b4-4042-b928-7830a37ffe28
with aws_network_interface.eni["vpc-subnet-two"],
on main.tf line 20, in resource "aws_network_interface" "eni":
20: resource "aws_network_interface" "eni" {
I've followed this documenation and validated everything else is correct. I still can't seem to figure out what value should be set on subnet_id
Bonus cheeky points - I am trying to configure 2 EC2's, Should i give our eni a secondary private_ips?
The error means that your IP 172.16.10.100 is invalid for your subnet CIDR range 192.168.1.0/24 and 192.168.4.0/24. Obviously this is correct because your IP should be in the correct range. For example:
private_ips = ["192.168.1.100"] # for the first subnet
private_ips = ["192.168.4.100"] # for the second subnet

Terraform not destroying resource after condition is false

I am creating vpc endpoints using terraform. My condition is if we provide subnet IDs in .tfvars file, it would create the endpoints or else it won't.
The code is working when endpoints are being created.
Issue:
Once the endpoint is created, if I remove the subnet Ids from .tfvars file it only removes the subnets from endpoints.
Expectation:
It should destroy the endpoint.
Below is my code:
resource.tf
resource "aws_vpc_endpoint" "CloudFormation" {
count = var.cf_subnet_ids != [] ? 1 : 0
vpc_id = var.vpc_id
service_name = data.aws_vpc_endpoint_service.cloudformation.service_name
vpc_endpoint_type = "Interface"
security_group_ids = var.security_group_ids
subnet_ids = var.cf_subnet_ids
private_dns_enabled = true
}
resource "aws_vpc_endpoint" "Monitoring" {
count = var.mntr_subnet_ids != [] ? 1 : 0
vpc_id = var.vpc_id
service_name = data.aws_vpc_endpoint_service.monitoring.service_name
vpc_endpoint_type = "Interface"
security_group_ids = var.security_group_ids
subnet_ids = var.mntr_subnet_ids
private_dns_enabled = true
}
module.tf
module "VPC1" {
source = "./endpoints"
count = var.vpc_endpoints[0].vpc_id != "" ? 1 : 0
vpc_id = var.vpc_endpoints[0].vpc_id
cf_subnet_ids = var.vpc_endpoints[0].endpointCloudFormationPerVPC
mntr_subnet_ids = var.vpc_endpoints[0].endpointMonitoringPerVPC
}
module "VPC2" {
source = "./endpoints"
count = var.vpc_endpoints[1].vpc_id != "" ? 1 : 0
vpc_id = var.vpc_endpoints[1].vpc_id
cf_subnet_ids = var.vpc_endpoints[1].endpointCloudFormationPerVPC
mntr_subnet_ids = var.vpc_endpoints[1].endpointMonitoringPerVPC
}
env.tfvars
vpc_endpoints = [
{
vpc_id = "vpc-0a7c8cb62ae12ecb0"
vpc_cidr = ["10.150.2.0/23"]
endpointCloudFormationPerVPC = ["subnet-0367288ea9b4a0656", "subnet-0779a62471a3ee5b6"]
endpointMonitoringPerVPC = []
},
{
vpc_id = "vpc-0b085d19c3c35617f"
vpc_cidr = ["10.150.0.0/23"]
endpointCloudFormationPerVPC = ["subnet-0367288ea9b4a0656", "subnet-0779a62471a3ee5b6"]
endpointMonitoringPerVPC = ["subnet-0fd8da6ec6672c759"]
}
]
Please help.
It creates 3 Endpoints. 2 CF and 1 monitoring with above script. If I modify the .tfvars to below, it should delete the monitoring endpoint. Instead it removes the subnet from endpoint as in it modifies the endpoint instead of destroying it.
vpc_endpoints = [
{
vpc_id = "vpc-0a7c8cb62ae12ecb0"
vpc_cidr = ["10.150.2.0/23"]
endpointCloudFormationPerVPC = ["subnet-0367288ea9b4a0656"]
endpointMonitoringPerVPC = []
},
{
vpc_id = "vpc-0b085d19c3c35617f"
vpc_cidr = ["10.150.0.0/23"]
endpointCloudFormationPerVPC = ["subnet-0367288ea9b4a0656"]
endpointMonitoringPerVPC = []
}
Currently in your declared module arguments, you are assigning the following value for cf_subnet_ids:
var.vpc_endpoints[0].endpointCloudFormationPerVPC
Given your vpc_endpoints variable as posted in the question, this argument value will be null after the list(object) is coalesced. Therefore, when we resolve this value in your config for the resource, it will be:
resource "aws_vpc_endpoint" "CloudFormation" {
count = null != [] ? 1 : 0
...
}
Since null does not equal the empty list constructor [], this will resolve to the first returned value in the ternary 1. This means the resource will still be managed with a count of 1, and your resource will not be deleted.
The easiest and best practices way to begin fixing your config and resolve this unintended behavior would be to convert the <= 0.11 meta-argument count into the >= 0.12 meta-argument for_each: documentation.

Terraform conditional for AWS route tables

Using Terraform, I need to create a route table for a public subnet and private subnet. The resource for a 'public' route table is using gateway_id
resource "aws_route_table" "rt-public" {
route {
cidr_block = var.cidr_block
gateway_id = var.gateway_id
}
}
The 'private' route table is using nat_gateway_id:
resource "aws_route_table" "rt-private" {
route {
cidr_block = var.cidr_block
nat_gateway_id = var.gateway_id
}
}
I pass from the main.tf file a variable var.tier that indicates whether I need a 'public' or 'private' route table.
I tried the following (in the module):
resource "aws_route_table" "rt-public" {
count = var.tier == "Public" ? 1 : 0
route {
cidr_block = var.cidr_block
gateway_id = var.gateway_id
}
}
resource "aws_route_table" "rt-private" {
count = var.tier == "Private" ? 1 : 0
route {
cidr_block = var.cidr_block
nat_gateway_id = var.gateway_id
}
}
This works. But in the main.tf I also need to access the route table id. So I created an outputs.tf file as follows:
output "aws_rt_public_id" {
value = aws_route_table.rt-public.id
}
output "aws_rt_private_id" {
value = aws_route_table.rt-private.id
}
The issue is that when a 'public' route table is created, then the 'private' output is empty. I get the error message: aws_route_table.rt-private is empty tuple. The given key does not identify an element in this collection value.
Similar error message for the public version.
How can this be fixed using conditionals?
You can also use your condition, and return only output that is valid:
output "aws_rt_public_id" {
value = var.tier == "Public" ? aws_route_table.rt-public[0].id : null
}
output "aws_rt_private_id" {
value = var.tier == "Private" ? aws_route_table.rt-private[0].id : null
}
In the above the null, when chosen, will result in a given output removed.

Terraform GCP: The resource was not found for an external ip address

I'm trying to create the base VPC network on google cloud platform using terraform on which I could then launch instances, GKE etc, however I end up with the following error message:
Error: Error creating RouterNat: googleapi: Error 404: The resource 'projects/lol/regions/mars-north1/addresses/39.144.42.123' was not found, notFound
This is the minimal terraform code without variables which leads to this state:
module "gcp_vpc" {
count = var.project_type == "aws" ? 0 : 1
source = "terraform-google-modules/network/google"
version = "3.0.1"
project_id = var.project_id
network_name = "${var.project_name}-lol-vpc"
routing_mode = "GLOBAL"
subnets = [
{
subnet_name = "${var.project_name}-lol-primary-subnet-${count.index}"
subnet_ip = "10.222.0.0/28"
subnet_region = var.gcp_region
subnet_private_access = "true"
subnet_flow_logs = "true"
}
]
secondary_ranges = {
"${var.project_name}-lol-secondary-subnets" = [
{
count = length(var.public_subnets)
range_name = "${var.project_name}-lol-subnet-alias-${count.index}"
ip_cidr_range = var.public_subnets[count.index]
},
{
count = length(var.private_subnets)
range_name = "${var.project_name}-lol-private-subnet-${count.index}"
ip_cidr_range = var.private_subnets[count.index]
},
]
}
}
module "cloud-nat" {
count = var.project_type == "aws" ? 0 : 1
source = "terraform-google-modules/cloud-nat/google"
version = "~> 1.3"
project_id = var.project_id
region = var.gcp_region
router = "${var.project_name}-lol-router"
create_router = true
network = module.gcp_vpc[0].network_name
# subnetworks = module.gcp_vpc[0].subnets_self_links
nat_ips = google_compute_address.nat.*.address
source_subnetwork_ip_ranges_to_nat = "ALL_SUBNETWORKS_ALL_PRIMARY_IP_RANGES"
min_ports_per_vm = "128"
icmp_idle_timeout_sec = "15"
tcp_established_idle_timeout_sec = "600"
tcp_transitory_idle_timeout_sec = "15"
udp_idle_timeout_sec = "15"
}
resource "google_compute_address" "nat" {
count = var.project_type == "aws" ? 0 : length(var.public_subnets)
name = "${var.project_name}-lol-eip-nat-${count.index}"
project = var.project_id
region = var.gcp_region
}
output "gcp_nat_ips" {
value = google_compute_address.nat.*.address
}
However, I can see the external ip address 39.144.42.123 on the GCP web console. Can someone please help with where should I be looking at to solve this issue? Is it terraform, the terraform provider or GCP?

Terraform using output from module

I just started with Terraform infrastructure. Trying to create a vpc module that will contain code for vpc, subnets, internet gateway, rout table. Also creating a separate tf file for rds , which will refer to the vpc module and utilize the private subnets declared in vpc module.
Created a vpc module that has vpc.tf with following
provider "aws" {
region = var.region
}
terraform {
backend "s3" {}
}
resource "aws_vpc" "production-vpc" {
cidr_block = var.vpc_cidr
enable_dns_hostnames = true
tags = {
Name = "Dev-VPC"
}
}
// Private Subnets
resource "aws_subnet" "private-subnet-1" {
cidr_block = var.private_subnet_1_cidr
vpc_id = aws_vpc.production-vpc.id
availability_zone = "us-east-1a"
tags = {
Name = "Private-Subnet-1"
}
}
resource "aws_subnet" "private-subnet-2" {
cidr_block = var.private_subnet_2_cidr
vpc_id = aws_vpc.production-vpc.id
availability_zone = "us-east-1b"
tags = {
Name = "Private-Subnet-2"
}
}
The output.tf has following
output "private-subnet1-id" {
description = "Private Subnet1 Id"
value = aws_subnet.private-subnet-1.*.id
}
output "private-subnet2-id" {
description = "Private Subnet2 Id"
value = aws_subnet.private-subnet-2.*.id
}
The file is saved in folder \module\vpc folder
Created rds.tf as follows in folder \rds
provider "aws" {
region = var.region
}
terraform {
backend "s3" {}
}
module "vpc" {
source = "../module/vpc"
}
resource "aws_db_subnet_group" "subnetgrp" {
name = "dbsubnetgrp"
subnet_ids = [module.vpc.private-subnet1-id.id, module.vpc.private-subnet2-id.id]
}
When I run terraform plan , I get following error
Error: Unsupported attribute
on rds.tf line 16, in resource "aws_db_subnet_group" "subnetgrp":
16: subnet_ids = [module.vpc.private-subnet1-id.id, module.vpc.private-subnet2-id.id]
|----------------
| module.vpc.private-subnet1-id is tuple with 1 element
This value does not have any attributes.
Error: Unsupported attribute
on rds.tf line 16, in resource "aws_db_subnet_group" "subnetgrp":
16: subnet_ids = [module.vpc.private-subnet1-id.id, module.vpc.private-subnet2-id.id]
|----------------
| module.vpc.private-subnet2-id is tuple with 1 element
This value does not have any attributes.
You don't need the splat expression in the output.tf. Try the following,
output "private-subnet1-id" {
description = "Private Subnet1 Id"
value = aws_subnet.private-subnet-1.id
}
output "private-subnet2-id" {
description = "Private Subnet2 Id"
value = aws_subnet.private-subnet-2.id
}