AWS import vpc with Terraform - amazon-web-services

I'm wanted to know if there is possible in Terraform to get the Default VPC ID without need to write the ID or the Name on the manifest and save it on a variable. My idea is to invoke it only knowing that is the Default VPC but not write the ID or Name, just because is the Default VPC.
Thank you
FT

This will get you a reference to the default VPC in the current AWS region:
data "aws_vpc" "default" {
default = true
}
This is documented here.
Note that this gives you a reference to the VPC, so you can pass the ID to other resources. Terraform does not manage the VPC when you do this, it simply references it. This is different from terraform import which causes Terraform to start managing the VPC, and requires that you pass it the VPC ID.

Related

How to get the default vpc id with terraform

I am trying to get the vpc_id of default vpc in my aws account using terraform
This is what I tried but it gives an error
Error: Invalid data source
this is what I tried:
data "aws_default_vpc" "default" {
}
# vpc
resource "aws_vpc" "kubernetes-vpc" {
cidr_block = "${var.vpc_cidr_block}"
enable_dns_hostnames = true
tags = {
Name = "kubernetes-vpc"
}
}
The aws_default_vpc is indeed not a valid data source. But the aws_vpc data source does have a boolean default you can use to choose the default vpc:
data "aws_vpc" "default" {
default = true
}
For completeness, I'll add that an aws_default_vpc resource exists that also manages the default VPC and implements the resource life-cycle without really creating the VPC* but would make changes in the resource like changing tags (and that includes its name).
* Unless you forcefully destroy the default VPC
From the docs:
This is an advanced resource and has special caveats to be aware of when using it. Please read this document in its entirety before using this resource.
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/default_vpc
This
resource "aws_default_vpc" "default" {
}
will do.
I think this is convenient for terraform projects managing a whole AWS account, but I would advise against using it whenever multiple terraform projects are deployed in a single organization account. You should better stay with #blokje5's answer in that case.

How to block Terraform from deleting an imported resource?

I'm brand new to Terraform so I'm sure i'm missing something, but the answers i'm finding don't seem to be asking the same question I have.
I have an AWS VPC/Security Group that we need our EC2 instances to be created under and this VPC/SG is already created. To create an EC2 instance, Terraform requires that if I don't have a default VPC, I must import my own. But once I import and apply my plan, when I wish to destroy it, its trying to destroy my VPC as well. How do I encapsulate my resources so when I run "terraform apply", I can create an EC2 instance with my imported VPC, but when I run "terraform destroy" I only destroy my EC2 instance?
In case anyone wants to mention, I understand that:
lifecycle = {
prevent_destroy = true
}
is not what I'm looking for.
Here is my current practice code.
resource "aws_vpc" "my_vpc" {
cidr_block = "xx.xx.xx.xx/24"
}
provider "aws" {
region = "us-west-2"
}
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"]
}
owners = ["099720109477"] # Canonical
}
resource "aws_instance" "web" {
ami = "${data.aws_ami.ubuntu.id}"
instance_type = "t3.nano"
vpc_security_group_ids = ["sg-0e27d851dxxxxxxxxxx"]
subnet_id = "subnet-0755c2exxxxxxxx"
tags = {
Name = "HelloWorld"
}
}
Terraform should not require you to deploy or import a VPC in order to deploy an EC2 instance into it. You should be able to reference the VPC, subnets and security groups by id so TF is aware of your existing network infrastructure just like you've already done for SGs and subnets. All you should need to deploy the EC2 instance "aws_instance" is give it an existing subnet id in the existing VPC like you already did. Why do you say deploying or importing a VPC is required by Terraform? What error or issue do you have deploying without the VPC and just using the existing one?
You can protect the VPC through AWS if you really wanted to, but I don't think you really want to import the VPC into your Terraform state and let Terraform manage it here. Sounds like you want the VPC to service other resources, maybe applications manually deployed or through other TF stacks, and the VPC to live independent of anyone application deployment.
To answer the original question, you can use a data source and match your VPC by id or tag name :
data "aws_vpc" "main" {
tags = {
Name = "main_vpc"
}
}
Or
data "aws_vpc" "main" {
id = "vpc-nnnnnnnn"
}
Then refer to it with : data.aws_vpc.main
Also, if you already included your VPC but would like not to destroy it while remove it from your state, you can manage to do it with the terraform state command : https://www.terraform.io/docs/commands/state/index.html

Cloud Formation: How to get VPC from Subnet Id

I have a Cloud Formation to set up an EC2 instance. I'm currently using the Parameters to specify the Subnet Id for the EC2 instance as well as the VPC Id for the Security Group (to be used in turn by the EC2 instance).
In my situation the Subnet Id specified is required to be part of the VPC and I'd like to only have to specify the Subnet Id in the Parameters. But I can't find a way to derive the VPC from the Subnet Id (http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-subnet.html)
I see the GetAtt function can be used to return resource attributes. Is there something equivalent to return resource properties?
From the documentation Fn:GetAtt, you can only retrieve AvailabilityZone and Ipv6CidrBlocks details of the Subnet. There is no inbuilt support to get VpcId of the given subnet in CFn Templates.
There is a work-around though. If you are using the aws-cli documentation, you can use the describe-subnets method to fetch the VpcId of the required subnet and pass it as input to the Cloudformation template create_stack call.
This method works even if you are using any SDK. for example, in Java.
//pseudo code only!
DescribeSubnetsRequest request = new DescribeSubnetsRequest();
request.withSubnetIds("subnet-abcdefgh");
DescribeSubnetsResult result = awsClient.describeSubnets(request);
String myVpc = result.getSubnets().get(0).getVpcId();
// add the above VPC Id to the parameters of your Cloud formation template create stack request.
Hope this helps.
I created a small project called cli2cloudformation. Using that you're able to execute cli commands inside your cloudformation stack and use the results of the commands.
Just check it here. I hope it helps you.

How can I setup an AWS lambda to access resources in two, separate VPCs?

I'm using Terraform to build an API + corresponding lambda functions.
I have some other infrastructure, which I'd like to think is nicely set up (maybe I'm wrong?):
2 VPCs (let's just call'em test and prod)
Private & public subnets in each VPC
RDS DBs launched in the private subnets
All resources are identical on both VPCs; e.g. there's a test-private-subnet and a prod-private-subnet with exactly the same specs, same for DBs, etc.
Now, I'm working on the API and the lambdas that will power said API.
I don't feel like I need a test & prod API gateway and test & prod lambdas:
lambda code will be the same, just acting on different DB
you can use API stage_variables, with different ips, to achieve a test vs prod environment for the API
But when I try and setup a lambda with the vpc_config block (cause I need it to be associated with the security group that's allowed ingress on the DBs), I get the following error:
Error applying plan:
1 error(s) occurred:
* module.lambdas.aws_lambda_function.api-lambda-users: 1 error(s) occurred:
* aws_lambda_function.api-lambda-users: Error creating Lambda function: InvalidParameterValueException: Security Groups are required to be in the same VPC.
status code: 400, request id: xxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx
My lambda config looks like this:
resource "aws_lambda_function" "api-lambda-users" {
provider = "PROVIDER"
function_name = "users"
s3_key = "users/${var.lambda-package-name}"
s3_bucket = "${var.api-lambdas-bucket}"
role = "${aws_iam_role.lambda-role.arn}"
handler = "${var.handler-name}"
runtime = "${var.lambda-runtime}"
vpc_config {
security_group_ids = [
//"${data.aws_security_group.prod-lambda.id}",
"${data.aws_security_group.test-lambda.id}"
]
subnet_ids = [
//"${data.aws_subnet.prod-primary.id}",
"${data.aws_subnet.test-primary.id}"
]
}
}
Notice I'd ideally like to just specify them, together, in their corresponding lists.
Am I missing something?
Suggestions?
Any help, related or not, is much appreciated.
Lambda running inside a vpc is subject to the same networking "rules" as ec2 instances. So it can't "exist" in two VPC's. If the lambda function needs to talk vpc resources in two separate VPC's you could use something like VPC peering or just run two copies of the function in the two different vpc's.
When you add VPC configuration to a Lambda function, it can only access resources in that VPC. If a Lambda function needs to access both VPC resources and the public Internet, the VPC needs to have a Network Address Translation (NAT) instance inside the VPC and a VPC Peering connection.

How to use default AWS VPC resources when created via Terraform

Trying to learn to use Terraform (v 0.3.7) with Amazon Web Services.
When I create a VPC using Terraform via the following:
resource "aws_vpc" "test-vpc" {
cidr_block = "${var.vpc_cidr}"
enable_dns_hostnames = true
tags {
Name = "test-vpc"
}
}
The VPC will have a main routing table and a "default" security group automatically created (I assume by AWS, rather than Terraform); these can be identified by the attributes on the created VPC: main_route_table_id and default_security_group_id.
While following this tutorial it talks about creating your own default security group and routing table - it makes no mention of the default ones that will get created (even if you create your own routing table, the "main" one created by default will just remain sitting there, associated with no subnets or anything).
Shouldn't we be using the default resource that created with a VPC? Especially the routing table, will there be any effects because of not using the "main" routing table?
And if I should be using the default resources, how do I do that with Terraform?
I couldn't see anything in the Terraform documentation about these default resources, and if I try to override them (for example by telling Terraform to create a security group with name default, I get errors).
AWS creates these default routing tables and sec groups. If you don't use them ( I know we don't) they are fine to get deleted.
Terraform throws errors if you require it to create default sec group as probably the group is already there or maybe this sec group name is reserved.
You can create one new resource "aws_security_group" ( https://terraform.io/docs/providers/aws/r/security_group.html )and have a dependency listed on the resource with
depends_on = ["aws_instance.instance-name-from-resource"]
for the instance thus sec group will be created first and then assign sec groups to the instance with "security_groups"