├── .gitignore ├── README.md ├── architecture-diagrams └── diagrams.ai ├── docs ├── PRESENTATION.md └── create-certificate-authority.md ├── example ├── dev │ └── main.tf └── modules │ ├── backend │ ├── main.tf │ └── variables.tf │ ├── vpc │ ├── main.tf │ ├── output.tf │ └── variables.tf │ └── vpn │ ├── main.tf │ └── variables.tf ├── tf-network-lesson-code-2-15 ├── dev │ └── main.tf └── modules │ ├── backend │ ├── main.tf │ └── variables.tf │ ├── google-network │ ├── main.tf │ ├── output.tf │ └── variables.tf │ ├── site-to-site-vpn │ ├── main.tf │ ├── output.tf │ └── variables.tf │ ├── vpc │ ├── main.tf │ ├── output.tf │ └── variables.tf │ └── vpn │ ├── main.tf │ └── variables.tf ├── tf-network-lesson-code-4-12 ├── dev │ └── main.tf └── modules │ ├── backend │ ├── main.tf │ └── variables.tf │ ├── vpc │ ├── main.tf │ ├── output.tf │ └── variables.tf │ └── vpn │ ├── main.tf │ └── variables.tf └── tf-network-lesson-code-6-21 ├── main.tf ├── modules ├── backend │ └── main.tf ├── vpc │ ├── main.tf │ ├── outputs.tf │ └── variables.tf └── vpn │ ├── main.tf │ └── variables.tf └── outputs.tf /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | temp 3 | 4 | # Local .terraform directories 5 | **/.terraform/* 6 | 7 | # .tfstate files 8 | *.tfstate 9 | *.tfstate.* 10 | 11 | # Crash log files 12 | crash.log 13 | 14 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 15 | # .tfvars files are managed as part of configuration and so should be included in 16 | # version control. 17 | # 18 | # example.tfvars 19 | 20 | # Ignore override files as they are usually used to override resources locally and so 21 | # are not checked in 22 | override.tf 23 | override.tf.json 24 | *_override.tf 25 | *_override.tf.json 26 | 27 | # Include override files you do wish to add to version control using negated pattern 28 | # 29 | # !example_override.tf 30 | 31 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 32 | # example: *tfplan* 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # production-ready-terraform 2 | Production Ready Terraform 3 | 4 | ## Set up 5 | - Install AWS CLI - https://docs.aws.amazon.com/cli/latest/userguide/getting-started-quickstart.html 6 | - Initialize project 7 | ``` 8 | cd example/dev 9 | terraform init 10 | ``` 11 | 12 | - Create Certificate authority, server key/cert, and client key/cert 13 | - Follow this guide: [docs/create-certificate-authority.md](create-certificate-authority.md) 14 | - More reading: [AWS Docs](https://docs.aws.amazon.com/vpn/latest/clientvpn-admin/client-authentication.html) 15 | 16 | - Deploy project 17 | ``` 18 | terraform apply 19 | ``` 20 | -------------------------------------------------------------------------------- /architecture-diagrams/diagrams.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jimbol/production-ready-terraform/d88c8eaa251701147b2bcbe952c4b3c2da512547/architecture-diagrams/diagrams.ai -------------------------------------------------------------------------------- /docs/PRESENTATION.md: -------------------------------------------------------------------------------- 1 | ## Pre req 2 | - Create AWS account 3 | - Install AWS CLI 4 | - Install Terraform 5 | 6 | ## Getting started 7 | - Set up folders 8 | - Discuss folder stucture 9 | 10 | - Create provider 11 | 12 | - Add EC2 instance 13 | - Look at terraform.tfstate that is generated 14 | - Terraform generates a static configuration called the terraform state 15 | - When using the state to run, terraform can deploy deterministically. It will deploy the same resources each time based on the config 16 | - This is where TF keep track of what is deployed and where. It is a reflection of what is in live in your provider 17 | 18 | - Discuss storing state remotely 19 | - This state isn't too useful if we cannot collaborate using it. 20 | - We can store the state remotely using terraform's "backend system" 21 | 22 | - Create back end 23 | - Discuss modules in Terraform 24 | - set up s3 bucket 25 | - Set up state lock table in dynamodb 26 | 27 | - Why use VPC 28 | - Its how you create a network on AWS. 29 | - Allows secure connection to on-premisis networks 30 | - Provides security options 31 | - Break 32 | 33 | - Understanding VPCs 34 | - Architectural Overview 35 | - Create subnets assign CIDR block (or an IP range) to each 36 | - Discuss connecting to the internet 37 | - How IPv4 CIDR blocks work - Quick version 38 | - Ranges of IP addresses 39 | - Some are reserved for the public internet 40 | - Network 10.0.0.0/16 - 32bit - 16 = 16. 2^16 = 65536 41 | - 10.0.0.0 - 10.0.255.255 42 | - Private subnet 10.0.1.1 - 10.0.1.254 43 | - Public subnet 10.0.2.1 - 10.0.2.254 44 | 45 | - Set up VPC 46 | - Pick CIDR block 47 | - Deploy it and see it in AWS 48 | - Create Public Subnet 49 | - Create Private Subnet 50 | 51 | - Public subnet 52 | - Set up internet gateway, attach to public subnet via a route table 53 | - Set up internet gateway. 54 | - Used for incoming AND outgoing traffic. 55 | - Use for apis 56 | - TODO add EC2 to public subnet and test 57 | 58 | - Private subnet 59 | - Create a NAT Gateway and add it to the public subnet 60 | - Creat an Elastic IP 61 | - IP that will be used when making requests to the internet 62 | - The NAT Gateway needs to be in the public subnet so that it can reach the internet 63 | - Add Route table for Private subnet that points outgoing traffic to the nat gateway 64 | 65 | - Client VPN 66 | - What we're going to do: 67 | - Set up a VPN 68 | - Accessed via Mutual authentication (certificate-based) 69 | - You can use Active directory or single sign-on instead 70 | - Create a CA (certificate authority) 71 | - Guides 72 | - [docs/create-certificate-authority.md](create-certificate-authority.md) 73 | - [AWS Docs](https://docs.aws.amazon.com/vpn/latest/clientvpn-admin/client-authentication.html) 74 | - Create a server certificate and key 75 | - Create client cert and key 76 | - Create a certificate chain 77 | - Create Terraform resources 78 | - aws_acm_certificate 79 | - aws_ec2_client_vpn_endpoint 80 | 81 | - Site to site VPN 82 | - Guide - https://www.silect.is/blog/multi-cloud-vpn-terraform/ 83 | - What we're going to do 84 | - Set up a quick Google Cloud network with an instance of whatever the heck they have, for testing 85 | - Set up a aws_vpn_gateway 86 | - Creat an aws_customer_gateway for our peer at google 87 | -------------------------------------------------------------------------------- /docs/create-certificate-authority.md: -------------------------------------------------------------------------------- 1 | ## Download easy rsa 2 | ``` 3 | git clone https://github.com/OpenVPN/easy-rsa.git 4 | cd easy-rsa/easyrsa3 5 | ``` 6 | 7 | ## Initialize the PKI environment (Public Key Infrastructure) 8 | ``` 9 | ./easyrsa init-pki 10 | ``` 11 | 12 | ## Create a new Certificate Authority (CA) 13 | This is what our server can use to validate certificates. Locally we will use it to generate certificates. 14 | ``` 15 | ./easyrsa build-ca nopass 16 | ``` 17 | 18 | ## Generate the server cert and key 19 | ``` 20 | ./easyrsa build-server-full server nopass 21 | ``` 22 | 23 | ## Generate client config 24 | When adding a user, generate a separate config for each user. This allows you to revoke access from the user later. 25 | 26 | ``` 27 | ./easyrsa build-client-full jhall.oreilly.com nopass 28 | ``` 29 | 30 | "jhall.oreilly.com" doesn't have to be a working domain. Its a name for the client. 31 | 32 | ### Import the certificate 33 | ``` 34 | aws acm import-certificate --certificate fileb://server.crt --private-key fileb://server.key --certificate-chain fileb://ca.crt 35 | ``` 36 | 37 | -------------------------------------------------------------------------------- /example/dev/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | aws = { 4 | source = "hashicorp/aws" 5 | version = "~>4.0" 6 | } 7 | google = { 8 | source = "hashicorp/google" 9 | version = "~>4.0" 10 | } 11 | } 12 | 13 | backend "s3" { 14 | encrypt = true 15 | bucket = "terraform-class-test-4-12-dev-state" 16 | key = "terraform-state/dev/terraform.tfstate" 17 | region = "us-east-2" 18 | 19 | dynamodb_table = "terraform-class-test-4-12-dev-lock" 20 | } 21 | } 22 | 23 | provider "aws" { 24 | region = "us-east-2" 25 | profile = "default" 26 | } 27 | 28 | locals { 29 | env = "dev" 30 | vpc_cidr = "10.0.0.0/16" 31 | public_subnet_cidr = "10.0.1.0/24" 32 | private_subnet_cidr = "10.0.2.0/24" 33 | google_vpc_cidr = "11.0.0.0/24" 34 | } 35 | 36 | module "backend" { 37 | source = "../modules/backend" 38 | env = local.env 39 | } 40 | 41 | module "vpc" { 42 | source = "../modules/vpc" 43 | env = local.env 44 | vpc_cidr = local.vpc_cidr 45 | } 46 | 47 | module "vpn" { 48 | source = "../modules/vpn" 49 | subnet_ids = [module.vpc.private_subnet_id, module.vpc.public_subnet_id] 50 | vpc_id = module.vpc.vpc_id 51 | vpc_cidr = local.vpc_cidr 52 | } 53 | 54 | 55 | resource "aws_security_group" "allow_ssh" { 56 | name = "allow_ssh" 57 | description = "Allows ssh connections and access to the internet" 58 | vpc_id = module.vpc.vpc_id 59 | 60 | ingress = [{ 61 | cidr_blocks = ["0.0.0.0/0"] 62 | description = "ssh ingress" 63 | protocol = "tcp" 64 | from_port = 22 65 | to_port = 22 66 | self = false 67 | 68 | ipv6_cidr_blocks = [] 69 | security_groups = [] 70 | prefix_list_ids = [] 71 | }] 72 | 73 | egress = [{ 74 | cidr_blocks = ["0.0.0.0/0"] 75 | description = "internet egress" 76 | protocol = "-1" 77 | from_port = 0 78 | to_port = 0 79 | 80 | self = false 81 | ipv6_cidr_blocks = [] 82 | security_groups = [] 83 | prefix_list_ids = [] 84 | }] 85 | } 86 | 87 | resource "aws_eip" "test_server_eip" { 88 | vpc = true 89 | instance = aws_instance.test_server.id 90 | associate_with_private_ip = aws_instance.test_server.private_ip 91 | } 92 | 93 | resource "aws_instance" "test_server" { 94 | ami = "ami-0f19d220602031aed" 95 | instance_type = "t2.nano" 96 | subnet_id = module.vpc.public_subnet_id 97 | vpc_security_group_ids = [aws_security_group.allow_ssh.id] 98 | 99 | key_name = "terraformclass" 100 | 101 | tags = { 102 | name: "public test server" 103 | } 104 | } 105 | 106 | resource "aws_instance" "private_test_server" { 107 | ami = "ami-0f19d220602031aed" 108 | instance_type = "t2.nano" 109 | subnet_id = module.vpc.private_subnet_id 110 | 111 | vpc_security_group_ids = [aws_security_group.allow_ssh.id] 112 | 113 | key_name = "terraformclass" 114 | 115 | tags = { 116 | "name" = "private test server" 117 | } 118 | } 119 | 120 | 121 | -------------------------------------------------------------------------------- /example/modules/backend/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_s3_bucket" "terraform_backend" { 2 | bucket = "terraform-class-test-4-12-${var.env}-state" 3 | 4 | tags = { 5 | name = "Remote terraform backend" 6 | env = var.env 7 | } 8 | } 9 | 10 | resource "aws_s3_bucket_versioning" "example" { 11 | bucket = aws_s3_bucket.terraform_backend.id 12 | 13 | versioning_configuration { 14 | status = "Enabled" 15 | } 16 | } 17 | 18 | resource "aws_s3_bucket_server_side_encryption_configuration" "example" { 19 | bucket = aws_s3_bucket.terraform_backend.id 20 | 21 | rule { 22 | apply_server_side_encryption_by_default { 23 | sse_algorithm = "AES256" 24 | } 25 | } 26 | } 27 | 28 | resource "aws_dynamodb_table" "terraform_state_lock" { 29 | name = "terraform-class-test-4-12-${var.env}-lock" 30 | 31 | hash_key = "LockID" 32 | read_capacity = 20 33 | write_capacity = 20 34 | 35 | attribute { 36 | name = "LockID" 37 | type = "S" 38 | } 39 | 40 | tags = { 41 | name = "DynamoDB that stores the lock for Terraform" 42 | env = var.env 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /example/modules/backend/variables.tf: -------------------------------------------------------------------------------- 1 | variable "env" { 2 | description = "Environment name" 3 | default = "dev" 4 | type = string 5 | } 6 | -------------------------------------------------------------------------------- /example/modules/vpc/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_vpc" "cloud_network" { 2 | cidr_block = var.vpc_cidr 3 | instance_tenancy = "default" 4 | 5 | tags = { 6 | name = "Cloud network" 7 | env = var.env 8 | } 9 | } 10 | 11 | resource "aws_subnet" "public_subnet" { 12 | vpc_id = aws_vpc.cloud_network.id 13 | cidr_block = "10.0.1.0/24" 14 | availability_zone = "us-east-2c" 15 | } 16 | 17 | resource "aws_internet_gateway" "public_internet_gateway" { 18 | vpc_id = aws_vpc.cloud_network.id 19 | } 20 | 21 | resource "aws_route_table" "public_route_table" { 22 | vpc_id = aws_vpc.cloud_network.id 23 | 24 | tags = { 25 | name = "Public route table" 26 | } 27 | } 28 | 29 | resource "aws_route" "public_route" { 30 | route_table_id = aws_route_table.public_route_table.id 31 | 32 | destination_cidr_block = "0.0.0.0/0" 33 | gateway_id = aws_internet_gateway.public_internet_gateway.id 34 | } 35 | 36 | resource "aws_route_table_association" "public_subnet_route_table" { 37 | subnet_id = aws_subnet.public_subnet.id 38 | route_table_id = aws_route_table.public_route_table.id 39 | } 40 | 41 | # Private subnet 42 | resource "aws_subnet" "private_subnet" { 43 | vpc_id = aws_vpc.cloud_network.id 44 | cidr_block = "10.0.2.0/24" 45 | availability_zone = "us-east-2b" 46 | } 47 | 48 | resource "aws_eip" "elastic_ip_for_nat_gateway" { 49 | vpc = true 50 | } 51 | 52 | resource "aws_nat_gateway" "nat_gateway" { 53 | subnet_id = aws_subnet.private_subnet.id 54 | allocation_id = aws_eip.elastic_ip_for_nat_gateway.id 55 | } 56 | 57 | resource "aws_route_table" "private_route_table" { 58 | vpc_id = aws_vpc.cloud_network.id 59 | } 60 | 61 | resource "aws_route" "private_route" { 62 | route_table_id = aws_route_table.private_route_table.id 63 | destination_cidr_block = "0.0.0.0/0" 64 | nat_gateway_id = aws_nat_gateway.nat_gateway.id 65 | } 66 | 67 | resource "aws_route_table_association" "private_subnet_route_table_association" { 68 | subnet_id = aws_subnet.private_subnet.id 69 | route_table_id = aws_route_table.private_route_table.id 70 | } 71 | -------------------------------------------------------------------------------- /example/modules/vpc/output.tf: -------------------------------------------------------------------------------- 1 | output "vpc_id" { 2 | description = "The id of our vpc" 3 | value = aws_vpc.cloud_network.id 4 | } 5 | 6 | output "public_subnet_id" { 7 | description = "id of our public subnet" 8 | value = aws_subnet.public_subnet.id 9 | } 10 | 11 | output "private_subnet_id" { 12 | description = "id of our private subnet" 13 | value = aws_subnet.private_subnet.id 14 | } 15 | 16 | output "private_route_table_id" { 17 | description = "The id for the private route table" 18 | value = aws_route_table.private_route_table.id 19 | } 20 | 21 | output "public_route_table_id" { 22 | description = "The id for the public route table" 23 | value = aws_route_table.public_route_table.id 24 | } 25 | -------------------------------------------------------------------------------- /example/modules/vpc/variables.tf: -------------------------------------------------------------------------------- 1 | variable "env" { 2 | description = "Env name" 3 | default = "dev" 4 | type = string 5 | } 6 | 7 | variable "vpc_cidr" { 8 | description = "Range of ip address available in the VPC" 9 | type = string 10 | } 11 | -------------------------------------------------------------------------------- /example/modules/vpn/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_acm_certificate" "vpn_certificate" { 2 | certificate_body = file("~/tfclass/server.crt") 3 | private_key = file("~/tfclass/server.key") 4 | certificate_chain = file("~/tfclass/ca.crt") 5 | } 6 | 7 | resource "aws_ec2_client_vpn_endpoint" "vpn" { 8 | description = "Vpn endpoint that we will use to connect to our network" 9 | vpc_id = var.vpc_id 10 | 11 | client_cidr_block = "10.1.0.0/22" 12 | server_certificate_arn = aws_acm_certificate.vpn_certificate.arn 13 | security_group_ids = [aws_security_group.vpn_access.id] 14 | split_tunnel = true 15 | 16 | authentication_options { 17 | type = "certificate-authentication" 18 | root_certificate_chain_arn = aws_acm_certificate.vpn_certificate.arn 19 | } 20 | 21 | connection_log_options { 22 | enabled = false 23 | } 24 | } 25 | 26 | resource "aws_security_group" "vpn_access" { 27 | vpc_id = var.vpc_id 28 | 29 | ingress = [{ 30 | protocol = "UDP" 31 | from_port = 443 32 | to_port = 443 33 | cidr_blocks = ["0.0.0.0/0"] 34 | description = "Incoming vpn connection" 35 | ipv6_cidr_blocks = [] 36 | prefix_list_ids = [] 37 | security_groups = [] 38 | self = false 39 | }] 40 | 41 | egress = [{ 42 | cidr_blocks = ["0.0.0.0/0"] 43 | protocol = "-1" 44 | to_port = 0 45 | from_port = 0 46 | description = "internet egress" 47 | 48 | self = false 49 | ipv6_cidr_blocks = [] 50 | prefix_list_ids = [] 51 | security_groups = [] 52 | }] 53 | } 54 | 55 | resource "aws_ec2_client_vpn_network_association" "vpn_network_association" { 56 | count = length(var.subnet_ids) 57 | subnet_id = var.subnet_ids[count.index] 58 | client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id 59 | } 60 | 61 | resource "aws_ec2_client_vpn_authorization_rule" "vpn_auth_rule" { 62 | target_network_cidr = var.vpc_cidr 63 | client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id 64 | authorize_all_groups = true 65 | } 66 | -------------------------------------------------------------------------------- /example/modules/vpn/variables.tf: -------------------------------------------------------------------------------- 1 | variable "vpc_id" { 2 | description = "ID of our VPC" 3 | type = string 4 | } 5 | 6 | variable "subnet_ids" { 7 | description = "These are the subnets that should be accessible via vpn" 8 | type = list 9 | } 10 | 11 | variable "vpc_cidr" { 12 | description = "The cidr block that can be accessed via vpn" 13 | type = string 14 | } 15 | -------------------------------------------------------------------------------- /tf-network-lesson-code-2-15/dev/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | aws = { 4 | source = "hashicorp/aws" 5 | version = "~>4.0" 6 | } 7 | } 8 | 9 | # backend "s3" { 10 | # encrypt = true 11 | # bucket = "terraform-class-2-16-dev-state" 12 | # key = "terraform-state/dev/terraform.tfstate" 13 | # region = "us-east-2" 14 | 15 | # dynamodb_table = "terraform-class-2-16-dev-state" 16 | # } 17 | } 18 | 19 | provider "aws" { 20 | region = "us-east-2" 21 | profile = "default" 22 | } 23 | 24 | locals { 25 | env = "dev" 26 | vpc_cidr = "10.0.0.0/16" 27 | public_subnet_cidr = "10.0.1.0/24" 28 | private_subnet_cidr = "10.0.2.0/24" 29 | google_vpc_cidr = "11.0.0.0/24" 30 | } 31 | 32 | module "backend" { 33 | source = "../modules/backend" 34 | env = local.env 35 | } 36 | 37 | module "vpc" { 38 | source = "../modules/vpc" 39 | env = local.env 40 | vpc_cidr = local.vpc_cidr 41 | } 42 | 43 | module "vpn" { 44 | source = "../modules/vpn" 45 | subnet_ids = [module.vpc.private_subnet_id, module.vpc.public_subnet_id] 46 | vpc_id = module.vpc.vpc_id 47 | vpc_cidr = local.vpc_cidr 48 | } 49 | 50 | module "site_to_site_vpn" { 51 | source = "../modules/site-to-site-vpn" 52 | vpc_id = module.vpc.vpc_id 53 | vpc_cidr = local.vpc_cidr 54 | google_vpc_cidr = local.google_vpc_cidr 55 | google_vpn_address = module.google_network.google_vpn_address 56 | aws_private_route_table_id = module.vpc.private_route_table_id 57 | aws_public_route_table_id = module.vpc.public_route_table_id 58 | } 59 | 60 | module "google_network" { 61 | source = "../modules/google-network" 62 | cidr_block = local.google_vpc_cidr 63 | aws_subnets = [local.private_subnet_cidr, local.public_subnet_cidr] 64 | aws_vpn_connection = { 65 | tunnel1_address = module.site_to_site_vpn.aws_vpn_connection.tunnel1_address, 66 | tunnel1_preshared_key = module.site_to_site_vpn.aws_vpn_connection.tunnel1_preshared_key, 67 | tunnel1_vgw_inside_address = module.site_to_site_vpn.aws_vpn_connection.tunnel1_vgw_inside_address, 68 | tunnel1_cgw_inside_address = module.site_to_site_vpn.aws_vpn_connection.tunnel1_cgw_inside_address, 69 | 70 | tunnel2_address = module.site_to_site_vpn.aws_vpn_connection.tunnel2_address, 71 | tunnel2_preshared_key = module.site_to_site_vpn.aws_vpn_connection.tunnel2_preshared_key, 72 | tunnel2_vgw_inside_address = module.site_to_site_vpn.aws_vpn_connection.tunnel2_vgw_inside_address, 73 | tunnel2_cgw_inside_address = module.site_to_site_vpn.aws_vpn_connection.tunnel2_cgw_inside_address, 74 | } 75 | } 76 | 77 | resource "aws_security_group" "allow_ssh" { 78 | name = "allow_ssh" 79 | description = "Allows ssh connections and access to the internet" 80 | vpc_id = module.vpc.vpc_id 81 | 82 | ingress = [{ 83 | cidr_blocks = ["0.0.0.0/0"] 84 | description = "ssh ingress" 85 | protocol = "tcp" 86 | from_port = 22 87 | to_port = 22 88 | self = false 89 | 90 | ipv6_cidr_blocks = [] 91 | security_groups = [] 92 | prefix_list_ids = [] 93 | }] 94 | 95 | egress = [{ 96 | cidr_blocks = ["0.0.0.0/0"] 97 | description = "internet egress" 98 | protocol = "-1" 99 | from_port = 0 100 | to_port = 0 101 | 102 | self = false 103 | ipv6_cidr_blocks = [] 104 | security_groups = [] 105 | prefix_list_ids = [] 106 | }] 107 | } 108 | 109 | resource "aws_eip" "test_server_eip" { 110 | vpc = true 111 | instance = aws_instance.test_server.id 112 | associate_with_private_ip = aws_instance.test_server.private_ip 113 | } 114 | 115 | resource "aws_instance" "test_server" { 116 | ami = "ami-0f19d220602031aed" 117 | instance_type = "t2.nano" 118 | subnet_id = module.vpc.public_subnet_id 119 | vpc_security_group_ids = [aws_security_group.allow_ssh.id] 120 | 121 | key_name = "terraformclass" 122 | 123 | tags = { 124 | name: "public test server" 125 | } 126 | } 127 | 128 | resource "aws_instance" "private_test_server" { 129 | ami = "ami-0f19d220602031aed" 130 | instance_type = "t2.nano" 131 | subnet_id = module.vpc.private_subnet_id 132 | 133 | vpc_security_group_ids = [aws_security_group.allow_ssh.id] 134 | 135 | key_name = "terraformclass" 136 | 137 | tags = { 138 | "name" = "private test server" 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /tf-network-lesson-code-2-15/modules/backend/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_s3_bucket" "terraform_backend" { 2 | bucket = "terraform-class-2-16-${var.env}-state" 3 | 4 | versioning { 5 | enabled = true 6 | } 7 | 8 | server_side_encryption_configuration { 9 | rule { 10 | apply_server_side_encryption_by_default { 11 | sse_algorithm = "AES256" 12 | } 13 | } 14 | } 15 | 16 | tags = { 17 | name = "Remote terraform backend" 18 | env = var.env 19 | } 20 | } 21 | 22 | resource "aws_dynamodb_table" "terraform_state_lock" { 23 | name = "terraform-class-2-16-${var.env}-state" 24 | 25 | hash_key = "LockID" 26 | read_capacity = 20 27 | write_capacity = 20 28 | 29 | attribute { 30 | name = "LockID" 31 | type = "S" 32 | } 33 | 34 | tags = { 35 | name = "DynamoDB that stores the lock for Terraform" 36 | env = var.env 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /tf-network-lesson-code-2-15/modules/backend/variables.tf: -------------------------------------------------------------------------------- 1 | variable "env" { 2 | description = "Environment name" 3 | default = "dev" 4 | type = string 5 | } 6 | -------------------------------------------------------------------------------- /tf-network-lesson-code-2-15/modules/google-network/main.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | project_id = "terraform-class-327014" 3 | google_region = "us-east1" 4 | network_name = "terraform-class-network" 5 | compute_address = "11.0.0.100" 6 | } 7 | 8 | provider "google" { 9 | credentials = file(pathexpand("~/.config/gcloud/${local.project_id}.json")) 10 | region = local.google_region 11 | project = local.project_id 12 | } 13 | 14 | resource "google_compute_network" "google_cloud_network" { 15 | name = local.network_name 16 | auto_create_subnetworks = "false" 17 | } 18 | 19 | resource "google_compute_subnetwork" "google_subnet1" { 20 | name = "google-subnet1" 21 | ip_cidr_range = var.cidr_block 22 | network = google_compute_network.google_cloud_network.name 23 | region = local.google_region 24 | } 25 | 26 | # Allow ping 27 | resource "google_compute_firewall" "gcp-allow-icmp" { 28 | name = "${google_compute_network.google_cloud_network.name}-gcp-allow-icmp" 29 | network = google_compute_network.google_cloud_network.name 30 | 31 | allow { 32 | protocol = "icmp" 33 | } 34 | 35 | source_ranges = [ 36 | "0.0.0.0/0", 37 | ] 38 | } 39 | 40 | # Allow SSH for iperf testing. 41 | resource "google_compute_firewall" "gcp-allow-ssh" { 42 | name = "${google_compute_network.google_cloud_network.name}-gcp-allow-ssh" 43 | network = google_compute_network.google_cloud_network.name 44 | 45 | allow { 46 | protocol = "tcp" 47 | ports = ["22"] 48 | } 49 | 50 | source_ranges = [ 51 | "0.0.0.0/0", 52 | ] 53 | } 54 | 55 | # Allow traffic from the VPN subnets. 56 | resource "google_compute_firewall" "gcp-allow-vpn" { 57 | name = "${google_compute_network.google_cloud_network.name}-gcp-allow-vpn" 58 | network = google_compute_network.google_cloud_network.name 59 | 60 | allow { 61 | protocol = "tcp" 62 | ports = ["0-65535"] 63 | } 64 | 65 | allow { 66 | protocol = "udp" 67 | ports = ["0-65535"] 68 | } 69 | 70 | source_ranges = ["10.0.0.0/16"] 71 | } 72 | 73 | # Allow TCP traffic from the Internet. 74 | resource "google_compute_firewall" "gcp-allow-internet" { 75 | name = "${google_compute_network.google_cloud_network.name}-gcp-allow-internet" 76 | network = google_compute_network.google_cloud_network.name 77 | 78 | allow { 79 | protocol = "tcp" 80 | ports = ["80"] 81 | } 82 | 83 | source_ranges = [ 84 | "0.0.0.0/0", 85 | ] 86 | } 87 | 88 | # Compute instance 89 | resource "google_compute_address" "google_compute_ip" { 90 | name = "google-compute-ip-${local.google_region}" 91 | region = local.google_region 92 | } 93 | 94 | resource "google_compute_instance" "test_gcp_instance" { 95 | name = "test-gcp-instance${local.google_region}" 96 | machine_type = "e2-micro" 97 | zone = "${local.google_region}-b" 98 | 99 | boot_disk { 100 | initialize_params { 101 | image = "debian-cloud/debian-9" 102 | } 103 | } 104 | 105 | network_interface { 106 | subnetwork = google_compute_subnetwork.google_subnet1.name 107 | network_ip = local.compute_address 108 | 109 | access_config { 110 | # Static IP 111 | nat_ip = google_compute_address.google_compute_ip.address 112 | } 113 | } 114 | } 115 | 116 | # VPN 117 | resource "google_compute_address" "gcp-vpn-ip" { 118 | name = "gcp-vpn-ip" 119 | region = local.google_region 120 | } 121 | 122 | resource "google_compute_vpn_gateway" "gcp-vpn-gateway" { 123 | name = "gcp-vpn-gateway-${local.google_region}" 124 | network = google_compute_network.google_cloud_network.name 125 | region = local.google_region 126 | } 127 | 128 | resource "google_compute_forwarding_rule" "fr_esp" { 129 | name = "fr-esp" 130 | ip_protocol = "ESP" 131 | ip_address = google_compute_address.gcp-vpn-ip.address 132 | target = google_compute_vpn_gateway.gcp-vpn-gateway.id 133 | } 134 | 135 | resource "google_compute_forwarding_rule" "fr_udp500" { 136 | name = "fr-udp500" 137 | ip_protocol = "UDP" 138 | port_range = "500" 139 | ip_address = google_compute_address.gcp-vpn-ip.address 140 | target = google_compute_vpn_gateway.gcp-vpn-gateway.id 141 | } 142 | 143 | resource "google_compute_forwarding_rule" "fr_udp4500" { 144 | name = "fr-udp4500" 145 | ip_protocol = "UDP" 146 | port_range = "4500" 147 | ip_address = google_compute_address.gcp-vpn-ip.address 148 | target = google_compute_vpn_gateway.gcp-vpn-gateway.id 149 | } 150 | 151 | # /* 152 | # * ----------VPN Tunnel1---------- 153 | # */ 154 | 155 | resource "google_compute_vpn_tunnel" "gcp-tunnel1" { 156 | name = "gcp-tunnel1" 157 | peer_ip = var.aws_vpn_connection.tunnel1_address 158 | shared_secret = var.aws_vpn_connection.tunnel1_preshared_key 159 | ike_version = 1 160 | 161 | target_vpn_gateway = google_compute_vpn_gateway.gcp-vpn-gateway.self_link 162 | 163 | router = google_compute_router.gcp-router1.name 164 | 165 | depends_on = [ 166 | google_compute_forwarding_rule.fr_esp, 167 | google_compute_forwarding_rule.fr_udp500, 168 | google_compute_forwarding_rule.fr_udp4500, 169 | ] 170 | } 171 | 172 | resource "google_compute_router" "gcp-router1" { 173 | name = "gcp-router1" 174 | region = local.google_region 175 | network = google_compute_network.google_cloud_network.name 176 | bgp { 177 | asn = 65000 178 | } 179 | } 180 | 181 | resource "google_compute_router_peer" "gcp-router1-peer" { 182 | name = "gcp-to-aws-bgp1" 183 | router = google_compute_router.gcp-router1.name 184 | region = google_compute_router.gcp-router1.region 185 | peer_ip_address = var.aws_vpn_connection.tunnel1_vgw_inside_address 186 | peer_asn = "64512" 187 | interface = google_compute_router_interface.router_interface1.name 188 | } 189 | 190 | resource "google_compute_router_interface" "router_interface1" { 191 | name = "gcp-to-aws-interface1" 192 | router = google_compute_router.gcp-router1.name 193 | region = google_compute_router.gcp-router1.region 194 | ip_range = "${var.aws_vpn_connection.tunnel1_cgw_inside_address}/30" 195 | vpn_tunnel = google_compute_vpn_tunnel.gcp-tunnel1.name 196 | } 197 | 198 | # /* 199 | # * ----------VPN Tunnel2---------- 200 | # */ 201 | 202 | resource "google_compute_vpn_tunnel" "gcp-tunnel2" { 203 | name = "gcp-tunnel2" 204 | peer_ip = var.aws_vpn_connection.tunnel2_address 205 | shared_secret = var.aws_vpn_connection.tunnel2_preshared_key 206 | ike_version = 1 207 | 208 | target_vpn_gateway = google_compute_vpn_gateway.gcp-vpn-gateway.self_link 209 | 210 | router = google_compute_router.gcp-router2.name 211 | 212 | depends_on = [ 213 | google_compute_forwarding_rule.fr_esp, 214 | google_compute_forwarding_rule.fr_udp500, 215 | google_compute_forwarding_rule.fr_udp4500, 216 | ] 217 | } 218 | 219 | resource "google_compute_router" "gcp-router2" { 220 | name = "gcp-router2" 221 | region = local.google_region 222 | network = google_compute_network.google_cloud_network.name 223 | bgp { 224 | asn = 65000 225 | } 226 | } 227 | 228 | resource "google_compute_router_peer" "gcp-router2-peer" { 229 | name = "gcp-to-aws-bgp2" 230 | router = google_compute_router.gcp-router2.name 231 | region = google_compute_router.gcp-router2.region 232 | peer_ip_address = var.aws_vpn_connection.tunnel2_vgw_inside_address 233 | peer_asn = "64512" 234 | interface = google_compute_router_interface.router_interface2.name 235 | } 236 | 237 | resource "google_compute_router_interface" "router_interface2" { 238 | name = "gcp-to-aws-interface2" 239 | router = google_compute_router.gcp-router2.name 240 | region = google_compute_router.gcp-router2.region 241 | ip_range = "${var.aws_vpn_connection.tunnel2_cgw_inside_address}/30" 242 | vpn_tunnel = google_compute_vpn_tunnel.gcp-tunnel2.name 243 | } 244 | -------------------------------------------------------------------------------- /tf-network-lesson-code-2-15/modules/google-network/output.tf: -------------------------------------------------------------------------------- 1 | output "google_vpn_address" { 2 | description = "ip address for the vpn" 3 | value = google_compute_address.gcp-vpn-ip.address 4 | } 5 | -------------------------------------------------------------------------------- /tf-network-lesson-code-2-15/modules/google-network/variables.tf: -------------------------------------------------------------------------------- 1 | variable "cidr_block" { 2 | description = "Google cloud cidr block" 3 | type = string 4 | } 5 | 6 | variable "aws_vpn_connection" { 7 | description = "The aws vpn connection object" 8 | type = object({ 9 | tunnel1_address = string, 10 | tunnel1_preshared_key = string, 11 | tunnel1_vgw_inside_address = string, 12 | tunnel1_cgw_inside_address = string, 13 | 14 | tunnel2_address = string, 15 | tunnel2_preshared_key = string, 16 | tunnel2_vgw_inside_address = string, 17 | tunnel2_cgw_inside_address = string, 18 | }) 19 | } 20 | 21 | variable "aws_subnets" { 22 | description = "The aws subnets that we want to be able to connect to" 23 | type = list 24 | } 25 | -------------------------------------------------------------------------------- /tf-network-lesson-code-2-15/modules/site-to-site-vpn/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_vpn_gateway" "vpn_gateway" { 2 | vpc_id = var.vpc_id 3 | } 4 | 5 | resource "aws_customer_gateway" "aws_to_google_gateway" { 6 | bgp_asn = 65000 7 | 8 | ip_address = var.google_vpn_address 9 | type = "ipsec.1" 10 | 11 | tags = { 12 | name = "aws to google gateway" 13 | } 14 | } 15 | 16 | resource "aws_vpn_connection" "aws_to_google_vpn_connection" { 17 | vpn_gateway_id = aws_vpn_gateway.vpn_gateway.id 18 | customer_gateway_id = aws_customer_gateway.aws_to_google_gateway.id 19 | 20 | type = "ipsec.1" 21 | static_routes_only = false 22 | 23 | remote_ipv4_network_cidr = var.vpc_cidr # 10.0.0.0/16 24 | local_ipv4_network_cidr = var.google_vpc_cidr # 11.0.0.0/24 25 | } 26 | 27 | resource "aws_vpn_gateway_route_propagation" "public_route_table_propagation" { 28 | route_table_id = var.aws_public_route_table_id 29 | vpn_gateway_id = aws_vpn_gateway.vpn_gateway.id 30 | } 31 | 32 | resource "aws_vpn_gateway_route_propagation" "private_route_table_propagation" { 33 | route_table_id = var.aws_private_route_table_id 34 | vpn_gateway_id = aws_vpn_gateway.vpn_gateway.id 35 | } 36 | -------------------------------------------------------------------------------- /tf-network-lesson-code-2-15/modules/site-to-site-vpn/output.tf: -------------------------------------------------------------------------------- 1 | output "aws_vpn_connection" { 2 | description = "The aws vpn connection" 3 | value = aws_vpn_connection.aws_to_google_vpn_connection 4 | } 5 | 6 | -------------------------------------------------------------------------------- /tf-network-lesson-code-2-15/modules/site-to-site-vpn/variables.tf: -------------------------------------------------------------------------------- 1 | variable "vpc_id" { 2 | description = "ID of our VPC" 3 | type = string 4 | } 5 | variable "vpc_cidr" { 6 | type = string 7 | } 8 | variable "google_vpc_cidr" { 9 | type = string 10 | } 11 | variable "google_vpn_address" { 12 | description = "The address of the google vpn" 13 | type = string 14 | } 15 | variable "aws_private_route_table_id" { 16 | type = string 17 | } 18 | variable "aws_public_route_table_id" { 19 | type = string 20 | } 21 | -------------------------------------------------------------------------------- /tf-network-lesson-code-2-15/modules/vpc/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_vpc" "cloud_network" { 2 | cidr_block = var.vpc_cidr 3 | instance_tenancy = "default" 4 | 5 | tags = { 6 | name = "Cloud network" 7 | env = var.env 8 | } 9 | } 10 | 11 | resource "aws_subnet" "public_subnet" { 12 | vpc_id = aws_vpc.cloud_network.id 13 | cidr_block = "10.0.1.0/24" 14 | availability_zone = "us-east-2c" 15 | } 16 | 17 | resource "aws_internet_gateway" "public_internet_gateway" { 18 | vpc_id = aws_vpc.cloud_network.id 19 | } 20 | 21 | resource "aws_route_table" "public_route_table" { 22 | vpc_id = aws_vpc.cloud_network.id 23 | 24 | route = [{ 25 | cidr_block = "0.0.0.0/0" 26 | gateway_id = aws_internet_gateway.public_internet_gateway.id 27 | 28 | carrier_gateway_id = "" 29 | destination_prefix_list_id = "" 30 | egress_only_gateway_id = "" 31 | instance_id = "" 32 | ipv6_cidr_block = "" 33 | local_gateway_id = "" 34 | nat_gateway_id = "" 35 | network_interface_id = "" 36 | transit_gateway_id = "" 37 | vpc_endpoint_id = "" 38 | vpc_peering_connection_id = "" 39 | }] 40 | 41 | tags = { 42 | name = "Public route table" 43 | } 44 | } 45 | 46 | resource "aws_route_table_association" "public_subnet_route_table" { 47 | subnet_id = aws_subnet.public_subnet.id 48 | route_table_id = aws_route_table.public_route_table.id 49 | } 50 | 51 | # Private subnet 52 | resource "aws_subnet" "private_subnet" { 53 | vpc_id = aws_vpc.cloud_network.id 54 | cidr_block = "10.0.2.0/24" 55 | availability_zone = "us-east-2b" 56 | } 57 | 58 | resource "aws_eip" "elastic_ip_for_nat_gateway" { 59 | vpc = true 60 | } 61 | 62 | resource "aws_nat_gateway" "nat_gateway" { 63 | subnet_id = aws_subnet.private_subnet.id 64 | allocation_id = aws_eip.elastic_ip_for_nat_gateway.id 65 | } 66 | 67 | resource "aws_route_table" "private_route_table" { 68 | vpc_id = aws_vpc.cloud_network.id 69 | 70 | route = [{ 71 | cidr_block = "0.0.0.0/0" 72 | nat_gateway_id = aws_nat_gateway.nat_gateway.id 73 | 74 | gateway_id = "" 75 | carrier_gateway_id = "" 76 | destination_prefix_list_id = "" 77 | egress_only_gateway_id = "" 78 | instance_id = "" 79 | ipv6_cidr_block = "" 80 | local_gateway_id = "" 81 | network_interface_id = "" 82 | transit_gateway_id = "" 83 | vpc_endpoint_id = "" 84 | vpc_peering_connection_id = "" 85 | }] 86 | } 87 | 88 | resource "aws_route_table_association" "private_subnet_route_table_association" { 89 | subnet_id = aws_subnet.private_subnet.id 90 | route_table_id = aws_route_table.private_route_table.id 91 | } 92 | -------------------------------------------------------------------------------- /tf-network-lesson-code-2-15/modules/vpc/output.tf: -------------------------------------------------------------------------------- 1 | output "vpc_id" { 2 | description = "The id of our vpc" 3 | value = aws_vpc.cloud_network.id 4 | } 5 | 6 | output "public_subnet_id" { 7 | description = "id of our public subnet" 8 | value = aws_subnet.public_subnet.id 9 | } 10 | 11 | output "private_subnet_id" { 12 | description = "id of our private subnet" 13 | value = aws_subnet.private_subnet.id 14 | } 15 | 16 | output "private_route_table_id" { 17 | description = "The id for the private route table" 18 | value = aws_route_table.private_route_table.id 19 | } 20 | 21 | output "public_route_table_id" { 22 | description = "The id for the public route table" 23 | value = aws_route_table.public_route_table.id 24 | } 25 | -------------------------------------------------------------------------------- /tf-network-lesson-code-2-15/modules/vpc/variables.tf: -------------------------------------------------------------------------------- 1 | variable "env" { 2 | description = "Env name" 3 | default = "dev" 4 | type = string 5 | } 6 | 7 | variable "vpc_cidr" { 8 | description = "Range of ip address available in the VPC" 9 | type = string 10 | } 11 | -------------------------------------------------------------------------------- /tf-network-lesson-code-2-15/modules/vpn/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_acm_certificate" "vpn_certificate" { 2 | certificate_body = file("~/tfclass/server.crt") 3 | private_key = file("~/tfclass/server.key") 4 | certificate_chain = file("~/tfclass/ca.crt") 5 | } 6 | 7 | resource "aws_ec2_client_vpn_endpoint" "vpn" { 8 | description = "Vpn endpoint that we will use to connect to our network" 9 | 10 | client_cidr_block = "10.1.0.0/22" 11 | server_certificate_arn = aws_acm_certificate.vpn_certificate.arn 12 | split_tunnel = true 13 | 14 | authentication_options { 15 | type = "certificate-authentication" 16 | root_certificate_chain_arn = aws_acm_certificate.vpn_certificate.arn 17 | } 18 | 19 | connection_log_options { 20 | enabled = false 21 | } 22 | } 23 | 24 | resource "aws_security_group" "vpn_access" { 25 | vpc_id = var.vpc_id 26 | 27 | ingress = [{ 28 | protocol = "UDP" 29 | from_port = 443 30 | to_port = 443 31 | cidr_blocks = ["0.0.0.0/0"] 32 | description = "Incoming vpn connection" 33 | ipv6_cidr_blocks = [] 34 | prefix_list_ids = [] 35 | security_groups = [] 36 | self = false 37 | }] 38 | 39 | egress = [{ 40 | cidr_blocks = ["0.0.0.0/0"] 41 | protocol = "-1" 42 | to_port = 0 43 | from_port = 0 44 | description = "internet egress" 45 | 46 | self = false 47 | ipv6_cidr_blocks = [] 48 | prefix_list_ids = [] 49 | security_groups = [] 50 | }] 51 | } 52 | 53 | resource "aws_ec2_client_vpn_network_association" "vpn_network_association" { 54 | count = length(var.subnet_ids) 55 | subnet_id = var.subnet_ids[count.index] 56 | security_groups = [aws_security_group.vpn_access.id] 57 | client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id 58 | } 59 | 60 | resource "aws_ec2_client_vpn_authorization_rule" "vpn_auth_rule" { 61 | target_network_cidr = var.vpc_cidr 62 | client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id 63 | authorize_all_groups = true 64 | } 65 | -------------------------------------------------------------------------------- /tf-network-lesson-code-2-15/modules/vpn/variables.tf: -------------------------------------------------------------------------------- 1 | variable "vpc_id" { 2 | description = "ID of our VPC" 3 | type = string 4 | } 5 | 6 | variable "subnet_ids" { 7 | description = "These are the subnets that should be accessible via vpn" 8 | type = list 9 | } 10 | 11 | variable "vpc_cidr" { 12 | description = "The cidr block that can be accessed via vpn" 13 | type = string 14 | } 15 | -------------------------------------------------------------------------------- /tf-network-lesson-code-4-12/dev/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | aws = { 4 | source = "hashicorp/aws" 5 | version = "~>4.0" 6 | } 7 | } 8 | 9 | # backend "s3" { 10 | # encrypt = true 11 | # bucket = "terraform-class-4-12-dev-tfstate" 12 | # key = "terraform-state/dev/terraform.tfstate" 13 | # region = "us-east-2" 14 | 15 | # dynamodb_table = "terraform-class-4-12-dev-lock" 16 | # } 17 | } 18 | 19 | provider "aws" { 20 | region = "us-east-2" 21 | profile = "default" 22 | } 23 | 24 | locals { 25 | env = "dev" 26 | vpc_cidr = "10.0.0.0/16" 27 | public_subnet_cidr = "10.0.1.0/24" 28 | private_subnet_cidr = "10.0.2.0/24" 29 | } 30 | 31 | # module "backend" { 32 | # source = "../modules/backend" 33 | # env = local.env 34 | # } 35 | 36 | module "vpc" { 37 | source = "../modules/vpc" 38 | env = local.env 39 | vpc_cidr = local.vpc_cidr 40 | public_subnet_cidr = local.public_subnet_cidr 41 | private_subnet_cidr = local.private_subnet_cidr 42 | } 43 | 44 | module "vpn" { 45 | source = "../modules/vpn" 46 | vpc_id = module.vpc.vpc_id 47 | subnet_ids = [module.vpc.public_subnet_id, module.vpc.private_subnet_id] 48 | vpc_cidr = local.vpc_cidr 49 | } 50 | 51 | resource "aws_eip" "test_server_eip" { 52 | vpc = true 53 | instance = aws_instance.test_server.id 54 | associate_with_private_ip = aws_instance.test_server.private_ip 55 | } 56 | 57 | resource "aws_instance" "test_server" { 58 | ami = "ami-0f19d220602031aed" 59 | instance_type = "t2.nano" 60 | subnet_id = module.vpc.public_subnet_id 61 | vpc_security_group_ids = [aws_security_group.allow_ssh.id] 62 | key_name = "terraformclass" 63 | 64 | tags = { 65 | Name = "test server" 66 | } 67 | } 68 | resource "aws_instance" "private_test_server" { 69 | ami = "ami-0f19d220602031aed" 70 | instance_type = "t2.nano" 71 | subnet_id = module.vpc.private_subnet_id 72 | vpc_security_group_ids = [aws_security_group.allow_ssh.id] 73 | key_name = "terraformclass" 74 | 75 | tags = { 76 | Name = "private test server" 77 | } 78 | } 79 | 80 | resource "aws_security_group" "allow_ssh" { 81 | name = "allow_ssh" 82 | description = "Allows ssh connections and access to the internet" 83 | vpc_id = module.vpc.vpc_id 84 | 85 | ingress = [{ 86 | cidr_blocks = ["0.0.0.0/0"] 87 | description = "ssh ingress" 88 | protocol = "tcp" 89 | from_port = 22 90 | to_port = 22 91 | 92 | self = false 93 | ipv6_cidr_blocks = [] 94 | security_groups = [] 95 | prefix_list_ids = [] 96 | }] 97 | 98 | egress = [{ 99 | cidr_blocks = ["0.0.0.0/0"] 100 | description = "internet access" 101 | protocol = "-1" 102 | from_port = 0 103 | to_port = 0 104 | 105 | self = false 106 | ipv6_cidr_blocks = [] 107 | security_groups = [] 108 | prefix_list_ids = [] 109 | }] 110 | } 111 | -------------------------------------------------------------------------------- /tf-network-lesson-code-4-12/modules/backend/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_s3_bucket" "terraform_backend" { 2 | bucket = "terraform-class-4-12-${var.env}-tfstate" 3 | 4 | lifecycle { 5 | prevent_destroy = false 6 | } 7 | 8 | # Terraform wont delete an S3 bucket with contents unless you force_destroy 9 | force_destroy = true 10 | 11 | tags = { 12 | Name = "Remote terraform backend" 13 | env = var.env 14 | } 15 | } 16 | 17 | resource "aws_s3_bucket_versioning" "state_versioning" { 18 | bucket = aws_s3_bucket.terraform_backend.id 19 | 20 | versioning_configuration { 21 | status = "Enabled" 22 | } 23 | } 24 | 25 | resource "aws_s3_bucket_server_side_encryption_configuration" "encyption_config" { 26 | bucket = aws_s3_bucket.terraform_backend.id 27 | 28 | rule { 29 | apply_server_side_encryption_by_default { 30 | sse_algorithm = "AES256" 31 | } 32 | } 33 | } 34 | 35 | resource "aws_dynamodb_table" "terraform_state_lock" { 36 | name = "terraform-class-4-12-${var.env}-lock" 37 | 38 | hash_key = "LockID" 39 | read_capacity = 20 40 | write_capacity = 20 41 | 42 | attribute { 43 | name = "LockID" 44 | type = "S" 45 | } 46 | 47 | tags = { 48 | Name = "dynamo db that stores lock for terraform" 49 | env = var.env 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tf-network-lesson-code-4-12/modules/backend/variables.tf: -------------------------------------------------------------------------------- 1 | variable "env" { 2 | description = "Environment Name" 3 | default = "dev" 4 | type = string 5 | } 6 | -------------------------------------------------------------------------------- /tf-network-lesson-code-4-12/modules/vpc/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_vpc" "cloud_network" { 2 | cidr_block = var.vpc_cidr 3 | instance_tenancy = "default" 4 | 5 | tags = { 6 | Name = "${var.env} Cloud Network" 7 | env = var.env 8 | } 9 | } 10 | 11 | # public subnet 12 | resource "aws_subnet" "public_subnet" { 13 | vpc_id = aws_vpc.cloud_network.id 14 | cidr_block = var.public_subnet_cidr 15 | availability_zone = "us-east-2c" 16 | } 17 | 18 | resource "aws_internet_gateway" "public_internet_gateway" { 19 | vpc_id = aws_vpc.cloud_network.id 20 | } 21 | 22 | resource "aws_route_table" "public_route_table" { 23 | vpc_id = aws_vpc.cloud_network.id 24 | 25 | tags = { 26 | Name = "public route table" 27 | } 28 | } 29 | 30 | resource "aws_route" "public_route" { 31 | route_table_id = aws_route_table.public_route_table.id 32 | 33 | destination_cidr_block = "0.0.0.0/0" 34 | gateway_id = aws_internet_gateway.public_internet_gateway.id 35 | } 36 | 37 | resource "aws_route_table_association" "public_route_table_association" { 38 | subnet_id = aws_subnet.public_subnet.id 39 | route_table_id = aws_route_table.public_route_table.id 40 | } 41 | 42 | # private subnet 43 | resource "aws_subnet" "private_subnet" { 44 | vpc_id = aws_vpc.cloud_network.id 45 | cidr_block = var.private_subnet_cidr 46 | availability_zone = "us-east-2b" 47 | } 48 | 49 | resource "aws_eip" "elastic_ip_for_nat_gateway" { 50 | vpc = true 51 | } 52 | 53 | resource "aws_nat_gateway" "nat_gateway" { 54 | subnet_id = aws_subnet.private_subnet.id 55 | allocation_id = aws_eip.elastic_ip_for_nat_gateway.id 56 | } 57 | 58 | resource "aws_route_table" "private_route_table" { 59 | vpc_id = aws_vpc.cloud_network.id 60 | } 61 | 62 | resource "aws_route" "private_route" { 63 | route_table_id = aws_route_table.private_route_table.id 64 | destination_cidr_block = "0.0.0.0/0" 65 | nat_gateway_id = aws_nat_gateway.nat_gateway.id 66 | } 67 | 68 | resource "aws_route_table_association" "private_route_table_association" { 69 | subnet_id = aws_subnet.private_subnet.id 70 | route_table_id = aws_route_table.private_route_table.id 71 | } 72 | -------------------------------------------------------------------------------- /tf-network-lesson-code-4-12/modules/vpc/output.tf: -------------------------------------------------------------------------------- 1 | output "vpc_id" { 2 | description = "vpc id" 3 | value = aws_vpc.cloud_network.id 4 | } 5 | output "public_subnet_id" { 6 | value = aws_subnet.public_subnet.id 7 | } 8 | output "private_subnet_id" { 9 | value = aws_subnet.private_subnet.id 10 | } 11 | -------------------------------------------------------------------------------- /tf-network-lesson-code-4-12/modules/vpc/variables.tf: -------------------------------------------------------------------------------- 1 | variable "env" { 2 | description = "Environment Name" 3 | default = "dev" 4 | type = string 5 | } 6 | variable "vpc_cidr" { 7 | description = "VPC CIDR block" 8 | type = string 9 | } 10 | variable "public_subnet_cidr" { 11 | description = "public subnet CIDR block" 12 | type = string 13 | } 14 | variable "private_subnet_cidr" { 15 | description = "private subnet CIDR block" 16 | type = string 17 | } 18 | -------------------------------------------------------------------------------- /tf-network-lesson-code-4-12/modules/vpn/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_acm_certificate" "vpn_certificate" { 2 | certificate_body = file("~/tfclass/server.crt") 3 | private_key = file("~/tfclass/server.key") 4 | certificate_chain = file("~/tfclass/ca.crt") 5 | } 6 | 7 | resource "aws_ec2_client_vpn_endpoint" "vpn" { 8 | description = "vpn endpoint" 9 | vpc_id = var.vpc_id 10 | 11 | client_cidr_block = "10.1.0.0/22" 12 | server_certificate_arn = aws_acm_certificate.vpn_certificate.arn 13 | security_group_ids = [aws_security_group.vpn_access.id] 14 | split_tunnel = true 15 | 16 | authentication_options { 17 | type = "certificate-authentication" 18 | root_certificate_chain_arn = aws_acm_certificate.vpn_certificate.arn 19 | } 20 | 21 | connection_log_options { 22 | enabled = false 23 | } 24 | } 25 | 26 | resource "aws_security_group" "vpn_access" { 27 | vpc_id = var.vpc_id 28 | 29 | ingress = [{ 30 | protocol = "UDP" 31 | from_port = 443 32 | to_port = 443 33 | cidr_blocks = ["0.0.0.0/0"] 34 | description = "Incoming vpn connection" 35 | ipv6_cidr_blocks = [] 36 | prefix_list_ids = [] 37 | security_groups = [] 38 | self = false 39 | }] 40 | 41 | egress = [{ 42 | cidr_blocks = ["0.0.0.0/0"] 43 | protocol = "-1" 44 | to_port = 0 45 | from_port = 0 46 | description = "internet egress" 47 | 48 | self = false 49 | ipv6_cidr_blocks = [] 50 | prefix_list_ids = [] 51 | security_groups = [] 52 | }] 53 | } 54 | 55 | resource "aws_ec2_client_vpn_network_association" "vpn_network_association" { 56 | count = length(var.subnet_ids) 57 | subnet_id = var.subnet_ids[count.index] 58 | client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id 59 | } 60 | 61 | resource "aws_ec2_client_vpn_authorization_rule" "vpn_auth_rule" { 62 | target_network_cidr = var.vpc_cidr 63 | client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id 64 | authorize_all_groups = true 65 | } 66 | -------------------------------------------------------------------------------- /tf-network-lesson-code-4-12/modules/vpn/variables.tf: -------------------------------------------------------------------------------- 1 | variable "vpc_id" { 2 | type = string 3 | } 4 | 5 | variable "subnet_ids" { 6 | type = list 7 | } 8 | 9 | variable "vpc_cidr" { 10 | type = string 11 | } 12 | -------------------------------------------------------------------------------- /tf-network-lesson-code-6-21/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_providers { 3 | aws = { 4 | source = "hashicorp/aws" 5 | version = "~>4.0" 6 | } 7 | } 8 | 9 | backend "s3" { 10 | encrypt = true 11 | bucket = "terraform-class-6-21-tfstate" 12 | key = "terraform-state/terraform.tfstate" 13 | region = "us-east-2" 14 | 15 | dynamodb_table = "terraform-class-6-21-lock" 16 | } 17 | } 18 | 19 | provider "aws" { 20 | region = "us-east-2" 21 | profile = "default" 22 | } 23 | 24 | locals { 25 | create_in_backend = terraform.workspace == "backend" ? 1 : 0 26 | create_in_other_envs = terraform.workspace == "backend" ? 0 : 1 27 | vpc_cidr = "10.0.0.0/16" 28 | public_subnet_cidr = "10.0.1.0/24" 29 | private_subnet_cidr = "10.0.2.0/24" 30 | } 31 | 32 | module "backend" { 33 | count = local.create_in_backend 34 | source = "./modules/backend" 35 | } 36 | 37 | module "vpc" { 38 | count = local.create_in_other_envs 39 | source = "./modules/vpc" 40 | vpc_cidr = local.vpc_cidr 41 | public_subnet_cidr = local.public_subnet_cidr 42 | private_subnet_cidr = local.private_subnet_cidr 43 | env = terraform.workspace 44 | } 45 | 46 | module "vpn" { 47 | source = "./modules/vpn" 48 | 49 | count = local.create_in_other_envs 50 | env = terraform.workspace 51 | vpc_id = module.vpc[0].vpc_id 52 | subnet_ids = [module.vpc[0].public_subnet_id, module.vpc[0].private_subnet_id] 53 | vpc_cidr = local.vpc_cidr 54 | } 55 | 56 | # ec2 57 | resource "aws_eip" "test_server_eip" { 58 | count = local.create_in_other_envs 59 | vpc = true 60 | instance = aws_instance.test_server[0].id 61 | associate_with_private_ip = aws_instance.test_server[0].private_ip 62 | } 63 | 64 | resource "aws_instance" "test_server" { 65 | count = local.create_in_other_envs 66 | ami = "ami-0f19d220602031aed" 67 | instance_type = "t2.nano" 68 | vpc_security_group_ids = [aws_security_group.allow_ssh[0].id] 69 | subnet_id = module.vpc[0].public_subnet_id 70 | 71 | key_name = "terraformclass" 72 | 73 | # user_data = <<-EOF 74 | # #!/bin/bash 75 | # python3 -m http.server 76 | # EOF 77 | 78 | tags = { 79 | Name = "${terraform.workspace} test server" 80 | } 81 | } 82 | 83 | resource "aws_instance" "private_test_server" { 84 | count = local.create_in_other_envs 85 | ami = "ami-0f19d220602031aed" 86 | instance_type = "t2.nano" 87 | vpc_security_group_ids = [aws_security_group.allow_ssh[0].id] 88 | subnet_id = module.vpc[0].private_subnet_id 89 | 90 | key_name = "terraformclass" 91 | 92 | # user_data = <<-EOF 93 | # #!/bin/bash 94 | # python3 -m http.server 95 | # EOF 96 | 97 | tags = { 98 | Name = "${terraform.workspace} private test server" 99 | } 100 | } 101 | 102 | resource "aws_security_group" "allow_ssh" { 103 | count = local.create_in_other_envs 104 | name = "allow_ssh" 105 | description = "Allows ssh connections and access to the outside internet" 106 | vpc_id = module.vpc[0].vpc_id 107 | 108 | 109 | ingress = [{ 110 | cidr_blocks = ["0.0.0.0/0"] 111 | description = "ssh ingress" 112 | protocol = "tcp" 113 | from_port = 22 114 | to_port = 22 115 | 116 | self = false 117 | security_groups = [] 118 | ipv6_cidr_blocks = [] 119 | prefix_list_ids = [] 120 | }] 121 | 122 | egress = [{ 123 | cidr_blocks = ["0.0.0.0/0"] 124 | description = "internet egress" 125 | protocol = "-1" 126 | from_port = 0 127 | to_port = 0 128 | 129 | self = false 130 | security_groups = [] 131 | ipv6_cidr_blocks = [] 132 | prefix_list_ids = [] 133 | }] 134 | } 135 | -------------------------------------------------------------------------------- /tf-network-lesson-code-6-21/modules/backend/main.tf: -------------------------------------------------------------------------------- 1 | # Tfstate bucket 2 | resource "aws_s3_bucket" "terraform_backend" { 3 | bucket = "terraform-class-6-21-tfstate" 4 | 5 | lifecycle { 6 | prevent_destroy = false 7 | } 8 | 9 | force_destroy = true 10 | 11 | tags = { 12 | Name = "Remote terraform backend" 13 | } 14 | } 15 | 16 | resource "aws_s3_bucket_versioning" "state_versioning" { 17 | bucket = aws_s3_bucket.terraform_backend.id 18 | 19 | versioning_configuration { 20 | status = "Enabled" 21 | } 22 | } 23 | 24 | resource "aws_s3_bucket_server_side_encryption_configuration" "encryption_config" { 25 | bucket = aws_s3_bucket.terraform_backend.id 26 | 27 | rule { 28 | apply_server_side_encryption_by_default { 29 | sse_algorithm = "AES256" 30 | } 31 | } 32 | } 33 | 34 | # Tfstate lock 35 | resource "aws_dynamodb_table" "terraform_state_lock" { 36 | name = "terraform-class-6-21-lock" 37 | 38 | hash_key = "LockID" 39 | read_capacity = 20 40 | write_capacity = 20 41 | 42 | attribute { 43 | name = "LockID" 44 | type = "S" 45 | } 46 | tags = { 47 | Name = "dynamo db that stores lock for terraform" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tf-network-lesson-code-6-21/modules/vpc/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_vpc" "cloud_network" { 2 | cidr_block = var.vpc_cidr 3 | instance_tenancy = "default" 4 | 5 | tags = { 6 | Name = "${var.env} Cloud Network" 7 | } 8 | } 9 | 10 | # public subnet 11 | resource "aws_subnet" "public_subnet" { 12 | vpc_id = aws_vpc.cloud_network.id 13 | cidr_block = var.public_subnet_cidr 14 | availability_zone = "us-east-2c" 15 | tags = { 16 | Name = "public subnet" 17 | } 18 | } 19 | 20 | resource "aws_internet_gateway" "public_internet_gateway" { 21 | vpc_id = aws_vpc.cloud_network.id 22 | } 23 | 24 | resource "aws_route_table" "public_route_table" { 25 | vpc_id = aws_vpc.cloud_network.id 26 | 27 | tags = { 28 | Name = "public route table" 29 | } 30 | } 31 | 32 | resource "aws_route" "public_route" { 33 | route_table_id = aws_route_table.public_route_table.id 34 | 35 | destination_cidr_block = "0.0.0.0/0" 36 | gateway_id = aws_internet_gateway.public_internet_gateway.id 37 | } 38 | 39 | resource "aws_route_table_association" "public_route_table_association" { 40 | subnet_id = aws_subnet.public_subnet.id 41 | route_table_id = aws_route_table.public_route_table.id 42 | } 43 | 44 | # private subnet 45 | resource "aws_subnet" "private_subnet" { 46 | vpc_id = aws_vpc.cloud_network.id 47 | cidr_block = var.private_subnet_cidr 48 | availability_zone = "us-east-2b" 49 | tags = { 50 | Name = "private subnet" 51 | } 52 | } 53 | 54 | resource "aws_eip" "elastic_ip_for_nat_gateway" { 55 | vpc = true 56 | } 57 | 58 | resource "aws_nat_gateway" "private_gateway" { 59 | subnet_id = aws_subnet.private_subnet.id 60 | allocation_id = aws_eip.elastic_ip_for_nat_gateway.id 61 | } 62 | 63 | resource "aws_route_table" "private_route_table" { 64 | vpc_id = aws_vpc.cloud_network.id 65 | 66 | tags = { 67 | Name = "private route table" 68 | } 69 | } 70 | 71 | resource "aws_route" "private_route" { 72 | route_table_id = aws_route_table.private_route_table.id 73 | 74 | destination_cidr_block = "0.0.0.0/0" 75 | nat_gateway_id = aws_nat_gateway.private_gateway.id 76 | } 77 | 78 | resource "aws_route_table_association" "private_route_table_association" { 79 | subnet_id = aws_subnet.private_subnet.id 80 | route_table_id = aws_route_table.private_route_table.id 81 | } 82 | -------------------------------------------------------------------------------- /tf-network-lesson-code-6-21/modules/vpc/outputs.tf: -------------------------------------------------------------------------------- 1 | output "vpc_id" { 2 | description = "vpc id" 3 | value = aws_vpc.cloud_network.id 4 | } 5 | 6 | output "public_subnet_id" { 7 | value = aws_subnet.public_subnet.id 8 | } 9 | 10 | output "private_subnet_id" { 11 | value = aws_subnet.private_subnet.id 12 | } 13 | -------------------------------------------------------------------------------- /tf-network-lesson-code-6-21/modules/vpc/variables.tf: -------------------------------------------------------------------------------- 1 | variable "env" { 2 | description = "Environment name" 3 | default = "dev" 4 | type = string 5 | } 6 | variable "vpc_cidr" { 7 | description = "VPC CIDR block" 8 | type = string 9 | } 10 | variable "public_subnet_cidr" { 11 | description = "public subnet CIDR block" 12 | type = string 13 | } 14 | variable "private_subnet_cidr" { 15 | description = "private subnet CIDR block" 16 | type = string 17 | } 18 | -------------------------------------------------------------------------------- /tf-network-lesson-code-6-21/modules/vpn/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_acm_certificate" "vpn_certificate" { 2 | certificate_body = file("~/tfclass/server.crt") 3 | private_key = file("~/tfclass/server.key") 4 | certificate_chain = file("~/tfclass/ca.crt") 5 | } 6 | 7 | resource "aws_ec2_client_vpn_endpoint" "vpn" { 8 | description = "vpn endpoint" 9 | vpc_id = var.vpc_id 10 | 11 | client_cidr_block = "10.1.0.0/22" 12 | server_certificate_arn = aws_acm_certificate.vpn_certificate.arn 13 | security_group_ids = [aws_security_group.vpn_access.id] 14 | 15 | split_tunnel = true 16 | 17 | authentication_options { 18 | type = "certificate-authentication" 19 | root_certificate_chain_arn = aws_acm_certificate.vpn_certificate.arn 20 | } 21 | 22 | connection_log_options { 23 | enabled = false 24 | } 25 | } 26 | 27 | resource "aws_security_group" "vpn_access" { 28 | vpc_id = var.vpc_id 29 | 30 | ingress = [{ 31 | protocol = "UDP" 32 | from_port = 443 33 | to_port = 443 34 | cidr_blocks = ["0.0.0.0/0"] 35 | description = "Incoming vpn connection" 36 | ipv6_cidr_blocks = [] 37 | prefix_list_ids = [] 38 | security_groups = [] 39 | self = false 40 | }] 41 | 42 | egress = [{ 43 | cidr_blocks = ["0.0.0.0/0"] 44 | protocol = "-1" 45 | to_port = 0 46 | from_port = 0 47 | description = "internet egress" 48 | 49 | self = false 50 | ipv6_cidr_blocks = [] 51 | prefix_list_ids = [] 52 | security_groups = [] 53 | }] 54 | } 55 | 56 | resource "aws_ec2_client_vpn_network_association" "vpn_network_association" { 57 | count = length(var.subnet_ids) 58 | subnet_id = var.subnet_ids[count.index] 59 | client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id 60 | } 61 | 62 | resource "aws_ec2_client_vpn_authorization_rule" "vpn_auth_rule" { 63 | target_network_cidr = var.vpc_cidr 64 | client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.vpn.id 65 | authorize_all_groups = true 66 | } 67 | -------------------------------------------------------------------------------- /tf-network-lesson-code-6-21/modules/vpn/variables.tf: -------------------------------------------------------------------------------- 1 | variable "env" { 2 | description = "Environment Name" 3 | default = "dev" 4 | type = string 5 | } 6 | 7 | variable "vpc_id" { 8 | type = string 9 | } 10 | 11 | variable "subnet_ids" { 12 | type = list 13 | } 14 | 15 | variable "vpc_cidr" { 16 | type = string 17 | } 18 | -------------------------------------------------------------------------------- /tf-network-lesson-code-6-21/outputs.tf: -------------------------------------------------------------------------------- 1 | output "test_ec2_id" { 2 | description = "test ec2 id" 3 | value = aws_instance.test_server[*].id 4 | } 5 | --------------------------------------------------------------------------------