├── .gitignore ├── CODE_OF_CONDUCT.md ├── README.md ├── main.tf ├── outputs.tf └── variables.tf /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled files 2 | *.tfstate 3 | *.tfstate.backup 4 | 5 | # Module directory 6 | .terraform/ 7 | .idea/ 8 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at ainestal@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # terraform-lambda-fixed-ip 2 | Provide a fixed IP (ElasticIP) to your AWS Lambdas. 3 | 4 | This is extremely useful when you need to connect to a service that filters IPs. Typical services use firewalls that can whitelist some IPs, by allowing your ElasticIP in the firewall rules you will be able to connect to the service from your Lambda. 5 | 6 | 7 | ## How it works 8 | - This terraform module creates a VPC in the eu-west-1 region (you can use a different region) 9 | - Creates a public and a private networks 10 | - Routes all the traffic from the private network to the public network 11 | - Routes all the traffic from the public network to internet 12 | - Assigns an elastic IP to the traffic coming from the public network, so it has a fixed IP 13 | 14 | 15 | ## How to use it 16 | - Include this module in your code: 17 | ``` 18 | module "lambdas_vpc" { 19 | source = "github.com/ainestal/terraform-lambda-fixed-ip?ref=0.2" 20 | } 21 | ``` 22 | - Plan terraform to see what is going to do: 23 | ``` 24 | terraform plan 25 | ``` 26 | - If you like what you see, apply the changes: 27 | ``` 28 | terraform apply 29 | ``` 30 | - Create your Lambdas inside the private subnet. 31 | - You can reference the vpc_id and the elastic ip id. If you are terraforming your lambda, the [lambda_function example](https://www.terraform.io/docs/providers/aws/r/lambda_function.html) would look like: 32 | ``` 33 | resource "aws_lambda_function" "test_lambda" { 34 | filename = "lambda_function_payload.zip" 35 | function_name = "lambda_function_name" 36 | role = "${aws_iam_role.iam_for_lambda.arn}" 37 | handler = "exports.test" 38 | source_code_hash = "${base64sha256(file("lambda_function_payload.zip"))}" 39 | runtime = "nodejs4.3" 40 | 41 | environment { 42 | variables = { 43 | foo = "bar" 44 | } 45 | } 46 | 47 | // Include this Lambda in the VPC that provides a Elastic IP 48 | vpc_config { 49 | subnet_ids = [ ${module.lambdas_vpc.private_subnet_id} ] 50 | 51 | security_group_ids = [ ] 52 | } 53 | } 54 | ``` 55 | - When your Lambdas run they will use your ElasticIP (and it will always be the same if you don't change it). 56 | 57 | 58 | ## Dependencies 59 | - Terraform >= 0.14.x , you can download it from [terraform downloads](https://www.terraform.io/downloads.html) 60 | - AWS account 61 | -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = var.region 3 | } 4 | 5 | 6 | //// VPC 7 | resource "aws_vpc" "lambdas" { 8 | cidr_block = var.vpc_cidr 9 | tags = merge( 10 | { 11 | Name = var.vpc_name 12 | }, 13 | var.custom_tags 14 | ) 15 | } 16 | 17 | 18 | //// Networks 19 | resource "aws_subnet" "lambdas-private" { 20 | cidr_block = var.private_subnet_cidr 21 | vpc_id = aws_vpc.lambdas.id 22 | tags = { 23 | Name = var.private_subnet_name 24 | } 25 | } 26 | 27 | resource "aws_subnet" "lambdas-public" { 28 | cidr_block = var.public_subnet_cidr 29 | vpc_id = aws_vpc.lambdas.id 30 | tags = { 31 | Name = var.public_subnet_name 32 | } 33 | } 34 | 35 | 36 | //// Gateways 37 | resource "aws_internet_gateway" "lambdas" { 38 | vpc_id = aws_vpc.lambdas.id 39 | } 40 | 41 | resource "aws_nat_gateway" "lambdas" { 42 | allocation_id = aws_eip.lambdas.id 43 | subnet_id = aws_subnet.lambdas-public.id 44 | tags = merge( 45 | { 46 | Name = var.nat_gateway_name 47 | }, 48 | var.custom_tags 49 | ) 50 | } 51 | 52 | 53 | //// Route tables Private 54 | resource "aws_route_table" "lambdas-private" { 55 | vpc_id = aws_vpc.lambdas.id 56 | 57 | route { 58 | cidr_block = "0.0.0.0/0" 59 | nat_gateway_id = aws_nat_gateway.lambdas.id 60 | } 61 | } 62 | 63 | resource "aws_route_table_association" "lambdas-private" { 64 | route_table_id = aws_route_table.lambdas-private.id 65 | subnet_id = aws_subnet.lambdas-private.id 66 | } 67 | 68 | 69 | //// Route tables Public 70 | resource "aws_route_table" "lambdas-public" { 71 | vpc_id = aws_vpc.lambdas.id 72 | 73 | route { 74 | cidr_block = "0.0.0.0/0" 75 | gateway_id = aws_internet_gateway.lambdas.id 76 | } 77 | } 78 | 79 | resource "aws_route_table_association" "lambdas-public" { 80 | route_table_id = aws_route_table.lambdas-public.id 81 | subnet_id = aws_subnet.lambdas-public.id 82 | } 83 | 84 | 85 | //// ElasticIp 86 | resource "aws_eip" "lambdas" { 87 | domain = "vpc" 88 | tags = merge( 89 | { 90 | Name = var.eip_name 91 | }, 92 | var.custom_tags 93 | ) 94 | } 95 | 96 | resource "aws_security_group" "allow_tls" { 97 | depends_on = [ 98 | aws_vpc.lambdas 99 | ] 100 | name = "allow_tls" 101 | description = "Allow TLS inbound traffic" 102 | vpc_id = aws_vpc.lambdas.id 103 | 104 | ingress { 105 | description = "TLS from VPC" 106 | from_port = 443 107 | to_port = 443 108 | protocol = "tcp" 109 | cidr_blocks = [var.vpc_cidr] 110 | ipv6_cidr_blocks = ["::/0"] 111 | } 112 | 113 | egress { 114 | from_port = 0 115 | to_port = 0 116 | protocol = "-1" 117 | cidr_blocks = ["0.0.0.0/0"] 118 | ipv6_cidr_blocks = ["::/0"] 119 | } 120 | 121 | tags = { 122 | Name = "allow_tls" 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | output "vpc_id" { 2 | value = aws_vpc.lambdas.id 3 | } 4 | 5 | output "private_subnet_id" { 6 | value = aws_subnet.lambdas-private.id 7 | } 8 | 9 | output "eip_id" { 10 | value = aws_eip.lambdas.id 11 | } 12 | 13 | output "aws_security_group" { 14 | value = aws_security_group.allow_tls 15 | } 16 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | variable "region" { default = "eu-west-2" } 2 | variable "vpc_cidr" { default = "10.0.0.0/16" } 3 | variable "vpc_name" { default = "lambdas-vpc" } 4 | variable "private_subnet_cidr" { default = "10.0.0.0/24" } 5 | variable "private_subnet_name" { default = "lambdas-private" } 6 | variable "public_subnet_cidr" { default = "10.0.1.0/24" } 7 | variable "public_subnet_name" { default = "lambdas-public" } 8 | variable "eip_name" { 9 | default ="Elastic IP for Lambdas VPC" 10 | } 11 | variable "nat_gateway_name" { 12 | default = "NAT Gateway for Lambdas VPC" 13 | } 14 | variable "custom_tags" { 15 | description = "A map of custom tags to apply to resources" 16 | type = map(string) 17 | default = {} 18 | } --------------------------------------------------------------------------------