diff --git a/.gitignore b/.gitignore index 856839462ccf382a13498c5fdce6b014bb43bcde..3377d94390180530dfaa2f15939b6f2ede90f68d 100644 --- a/.gitignore +++ b/.gitignore @@ -49,8 +49,11 @@ dist/ *.env .bundle/ !Pipfile.lock +!pdm.lock +!Gemfile.lock .terraform .terraform.* +!.terraform.lock.hcl tfplan *.tfstate* *.venv diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 833e902ada517548318a2fc9cfd1c1d4cd3514dd..8d09adde407c69b24da518d3c48a24fe4f7287d0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,3 +2,28 @@ include: - project: shore/ci-stuff file: templates/pre-commit.yml + - project: shore/ci-stuff + file: templates/terraform.yml + +default: + before_script: + - apt-get update + - apt-get install -y terraform + +AWS Terraform plan: + extends: .tf_plan + stage: test + #rules: &aws_tf_rules + # - changes: + # - ${TF_ROOT}/ + variables: &aws_tf_vars + TF_ROOT: Terraform/AWS + +AWS Terraform apply: + extends: .tf_apply + stage: deploy + #rules: *aws_tf_rules + needs: + - job: AWS Terraform plan + artifacts: true + variables: *aws_tf_vars diff --git a/Ansible/roles/router/files/nsd/shore.co.il b/Ansible/roles/router/files/nsd/shore.co.il index 6b987f394ca6f4c489ba8c5be75e53b5f7d712ed..ffae98d495aa20db44284bb65a70471046bc5dd0 100644 --- a/Ansible/roles/router/files/nsd/shore.co.il +++ b/Ansible/roles/router/files/nsd/shore.co.il @@ -2,7 +2,7 @@ $TTL 1h $ORIGIN shore.co.il. @ IN SOA ns1 hostmaster ( - 2021051901 + 2022041003 1h 5m 4w @@ -85,3 +85,8 @@ host01._domainkey IN TXT ("v=DKIM1\; k=rsa\;" _adsp._domainkey IN TXT "dkim=all;" _dmarc IN TXT "v=DMARC1;p=quarantine;pct=100;sp=reject;fo=1;rua=mailto:postmaster@shore.co.il;ruf=mailto:postmaster@shore.co.il;adkim=s;aspf=s" + +aws IN NS ns-117.awsdns-14.com. +aws IN NS ns-1352.awsdns-41.org. +aws IN NS ns-1664.awsdns-16.co.uk. +aws IN NS ns-750.awsdns-29.net. diff --git a/Terraform/AWS/.terraform.lock.hcl b/Terraform/AWS/.terraform.lock.hcl new file mode 100644 index 0000000000000000000000000000000000000000..c6c8a13e6ebc712af2f5b6e5a34b3b43fd5d8896 --- /dev/null +++ b/Terraform/AWS/.terraform.lock.hcl @@ -0,0 +1,22 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "4.9.0" + constraints = "~> 4.0" + hashes = [ + "h1:GtmIOZMkKmr9tMLWouHWiGXmKEL/diOTNar5XfOVLjs=", + "zh:084b83aef3335ad4f5e4b8323c6fe43c1ff55e17a7647c6a5cad6af519f72b42", + "zh:132e47ce69f14de4523b84b213cedf7173398acda14245b1ffe7747aac50f050", + "zh:2068baef7dfce3613f3b4f27314175e971f8db68d9cde9ec30b5659f80c68c6c", + "zh:63c6f489683d5f1ac55e82a0df387143ed22701d5f22c109a4d5c9924dd4e437", + "zh:8115fd21965954fa4568c09331e05bb29da967fab8d077419aed09954378e216", + "zh:8efdc95fde108f777ed9c79ae25dc17aea9771903250f5c5c8a4c726b90a345f", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:9d42a7bc34d84b70c1d1bcc215cabd63abbcbd0352b70bd84da6c3916634932f", + "zh:aacbcceb241aa475888c0869e87593182edeced3170c76a0c960dd9c905df449", + "zh:c7fe7904511052e4102870256819a1917177572cf684f0611ebf767f9c1fbaa8", + "zh:c8e07c3424663d1d0e7e32f4ade8099c19f6326d37c6da98104d90c986ff66fc", + "zh:e47cafbd38b56ef14fd8d727b4ffea847c166b1c684f585ee5fb78983b537248", + ] +} diff --git a/Terraform/AWS/main.tf b/Terraform/AWS/main.tf new file mode 100644 index 0000000000000000000000000000000000000000..128ca23dff3b4936f19d2de0b08816d015133819 --- /dev/null +++ b/Terraform/AWS/main.tf @@ -0,0 +1,152 @@ +terraform { + backend "http" {} + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.0" + } + } +} + +locals { + env = terraform.workspace == "default" ? "prod" : terraform.workspace + module = basename(abspath(path.root)) + name = "${local.project}-${local.module}-${local.env}" + project = "homelab" + common_tags = { + Environment = local.env + Module = local.module + Name = local.name + Project = local.project + } +} + +output "env" { + description = "Environment (prod/dev etc.)." + value = local.env +} + +output "module" { + description = "The name of the Terraform module, used to tagging resources." + value = local.module +} + +output "project" { + description = "The name of the Git project, used to tagging resources." + value = local.project +} + +variable "region" { + default = "us-east-1" + description = "AWS region." + type = string +} + +output "region" { + description = "AWS region." + value = var.region +} + +provider "aws" { + region = var.region + default_tags { + tags = local.common_tags + } +} + +data "aws_caller_identity" "current" {} + +locals { + account_id = data.aws_caller_identity.current.account_id +} + +output "account_id" { + description = "The AWS account ID." + value = local.account_id +} + +data "aws_iam_policy_document" "ec2_assume_policy" { + statement { + effect = "Allow" + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["ec2.amazonaws.com"] + } + } +} + +locals { + ec2_assume_policy = data.aws_iam_policy_document.ec2_assume_policy.json +} + +output "ec2_assume_policy" { + value = local.ec2_assume_policy + description = "IAM policy document for EC2 instance assuming a role." +} + +data "aws_iam_policy_document" "task_assume_policy" { + statement { + effect = "Allow" + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["ecs-tasks.amazonaws.com"] + } + } +} + +locals { + task_assume_policy = data.aws_iam_policy_document.task_assume_policy.json +} + +output "task_assume_policy" { + description = "IAM policy document for ECS tasks assuming a role." + value = local.task_assume_policy +} + +locals { + resource_group_query = { + ResourceTypeFilters = [ + "AWS::AllSupported", + ] + TagFilters = [ + { + Key = "Environment" + Values = [local.env, ] + }, + { + Key = "Module" + Values = [local.module, ] + }, + { + Key = "Project" + Values = [local.project, ] + }, + ] + } +} + +resource "aws_resourcegroups_group" "group" { + name = local.name + resource_query { + query = jsonencode(local.resource_group_query) + } +} + +locals { + resource_group_arn = aws_resourcegroups_group.group.arn + resource_group_name = aws_resourcegroups_group.group.name +} + +output "resource_group_arn" { + description = "ARN of the resource group." + value = local.resource_group_arn +} + +output "resource_group_name" { + description = "Name of the resource group." + value = local.resource_group_name +} diff --git a/Terraform/AWS/route53.tf b/Terraform/AWS/route53.tf new file mode 100644 index 0000000000000000000000000000000000000000..fc772abf1b443f05b826a63d871b5e0b3f4260d1 --- /dev/null +++ b/Terraform/AWS/route53.tf @@ -0,0 +1,52 @@ +resource "aws_route53_zone" "zone" { + name = "aws.shore.co.il" +} + +locals { + dns_zone_arn = aws_route53_zone.zone.arn + dns_zone_id = aws_route53_zone.zone.zone_id + dns_zone_name = aws_route53_zone.zone.name + dns_zone_name_servers = aws_route53_zone.zone.name_servers +} + +output "dns_zone_arn" { + description = "ARN of the Route53 DNS zone." + value = local.dns_zone_arn +} + +output "dns_zone_id" { + description = "ID of the Route53 DNS zone." + value = local.dns_zone_id +} + +output "dns_zone_name" { + description = "Name of the Router53 DNS zone." + value = local.dns_zone_name +} + +output "dns_zone_name_servers" { + description = "List of name servers of the Route53 DNS zone." + value = local.dns_zone_name_servers +} + +locals { + aws_caa_domain_names = [ + "amazon.com", + "amazontrust.com", + "awstrust.com", + "amazonaws.com", + ] +} + +resource "aws_route53_record" "caa" { + name = local.dns_zone_name + records = [ + "0 issue \"amazon.com\"", + "0 issue \"amazontrust.com\"", + "0 issue \"awstrust.com\"", + "0 issue \"amazonaws.com\"", + ] + ttl = 86400 + type = "CAA" + zone_id = local.dns_zone_id +} diff --git a/Terraform/AWS/vpc.tf b/Terraform/AWS/vpc.tf new file mode 100644 index 0000000000000000000000000000000000000000..a5691ffdcabfbd8dade1095c3ff6b4c38b539b8d --- /dev/null +++ b/Terraform/AWS/vpc.tf @@ -0,0 +1,304 @@ +variable "cidr_block" { + default = "172.31.0.0/16" + description = "CIDR block for the VPC." + type = string +} + +output "cidr_block" { + description = "CIDR block for the VPC." + value = var.cidr_block +} + +resource "aws_vpc" "vpc" { + cidr_block = var.cidr_block + tags = { + Name = local.env, + } +} + +locals { + vpc_arn = aws_vpc.vpc.arn + vpc_id = aws_vpc.vpc.id + vpc_name = aws_vpc.vpc.tags.Name +} + +output "vpc_arn" { + description = "ARN of the VPC." + value = local.vpc_arn +} + +output "vpc_id" { + description = "ID of the VPC." + value = local.vpc_id +} + +output "vpc_name" { + description = "Name of the VPC." + value = local.vpc_name +} + +resource "aws_internet_gateway" "gateway" { + vpc_id = local.vpc_id + tags = { + Name = local.env, + } +} + +locals { + internet_gateway_arn = aws_internet_gateway.gateway.arn + internet_gateway_id = aws_internet_gateway.gateway.id + internet_gateway_name = aws_internet_gateway.gateway.tags["Name"] +} + +output "internet_gateway_arn" { + description = "ARN of the internet gateway." + value = local.internet_gateway_arn +} + +output "internet_gateway_id" { + description = "ID of the internet gateway." + value = local.internet_gateway_id +} + +output "internet_gateway_name" { + description = "Name of the internet gateway." + value = local.internet_gateway_name +} + +variable "subnet_count" { + default = 3 + description = "Number of each private and public subnets." + type = number +} + +output "subnet_count" { + description = "Number of each private and public subnets." + value = var.subnet_count +} + +locals { + az_mapping = { + 1 = "a" + 2 = "b" + 3 = "c" + 4 = "d" + 5 = "e" + 6 = "f" + 7 = "g" + 8 = "h" + 9 = "i" + } +} + +resource "aws_subnet" "private" { + count = var.subnet_count + availability_zone = "${var.region}${local.az_mapping[count.index + 1]}" + cidr_block = cidrsubnet(var.cidr_block, 8, count.index) + map_public_ip_on_launch = false + vpc_id = local.vpc_id + tags = { + Name = "${local.env}-private-${local.az_mapping[count.index + 1]}" + Type = "private" + } +} + +locals { + private_subnet_arns = aws_subnet.private.*.arn + private_subnet_ids = aws_subnet.private.*.id + private_subnet_names = [for i in aws_subnet.private.*.tags : i["Name"]] +} + +output "private_subnet_arns" { + description = "List of private subnets ARNs." + value = local.private_subnet_arns +} + +output "private_subnet_ids" { + description = "List of private subnets IDs." + value = local.private_subnet_ids +} + +output "private_subnet_names" { + description = "List of private subnets names." + value = local.private_subnet_names +} + +resource "aws_subnet" "public" { + count = var.subnet_count + availability_zone = "${var.region}${local.az_mapping[count.index + 1]}" + cidr_block = cidrsubnet(var.cidr_block, 8, var.subnet_count + count.index) + map_public_ip_on_launch = true + vpc_id = local.vpc_id + tags = { + Name = "${local.env}-public-${local.az_mapping[count.index + 1]}" + Type = "public" + } +} + +locals { + public_subnet_arns = aws_subnet.public.*.arn + public_subnet_ids = aws_subnet.public.*.id + public_subnet_names = [for i in aws_subnet.public.*.tags : i["Name"]] +} + +output "public_subnet_arns" { + description = "List of public subnets ARNs." + value = local.public_subnet_arns +} + +output "public_subnet_ids" { + description = "List of public subnets IDs." + value = local.public_subnet_ids +} + +output "public_subnet_names" { + description = "List of public subnets names." + value = local.public_subnet_names +} + +resource "aws_eip" "nat_eip" { + count = var.subnet_count + vpc = true + tags = { + Name = "${local.env}-${local.az_mapping[count.index + 1]}" + } + depends_on = [ + aws_internet_gateway.gateway, + ] +} + +locals { + nat_gateway_eip_ids = aws_eip.nat_eip.*.id + nat_gateway_eip_names = [for i in aws_eip.nat_eip.*.tags : i["Name"]] +} + +output "nat_gateway_eip_ids" { + description = "List of Elastic IP IDs for the NAT gateway." + value = local.nat_gateway_eip_ids +} + +output "nat_gateway_eip_names" { + description = "List of Elastic IP names for the NAT gateway." + value = local.nat_gateway_eip_names +} + +resource "aws_nat_gateway" "gateway" { + count = var.subnet_count + allocation_id = local.nat_gateway_eip_ids[count.index] + subnet_id = local.public_subnet_ids[count.index] + tags = { + Name = "${local.env}-${local.az_mapping[count.index + 1]}" + } +} + +locals { + nat_gateway_ids = aws_nat_gateway.gateway.*.id + nat_gateway_names = [for i in aws_nat_gateway.gateway.*.tags : i["Name"]] +} + +output "nat_gateway_ids" { + description = "List of NAT gateway IDs." + value = local.nat_gateway_ids +} + +output "nat_gateway_names" { + description = "List of NAT gateway names." + value = local.nat_gateway_names +} + +resource "aws_route_table" "public" { + vpc_id = local.vpc_id + tags = { + Name = "${local.env}-public" + } + + route { + cidr_block = "0.0.0.0/0" + gateway_id = local.internet_gateway_id + } +} + +locals { + public_route_table_arn = aws_route_table.public.arn + public_route_table_id = aws_route_table.public.id + public_route_table_name = aws_route_table.public.tags["Name"] +} + +output "public_route_table_arn" { + description = "ARN of the routing table for the public subnets." + value = local.public_route_table_arn +} + +output "public_route_table_id" { + description = "ID of the routing table for the public subnets." + value = local.public_route_table_id +} + +output "public_route_table_name" { + description = "Name of the routing table for the public subnets." + value = local.public_route_table_name +} + +resource "aws_route_table_association" "public" { + for_each = toset(local.public_subnet_ids) + route_table_id = local.public_route_table_id + subnet_id = each.key +} + +locals { + public_route_table_association_ids = [for i in aws_route_table_association.public : i.id] +} + +output "public_route_table_association_ids" { + description = "List of the route table associations IDs for the public subnets." + value = local.public_route_table_association_ids +} + +resource "aws_route_table" "private" { + for_each = toset(local.nat_gateway_ids) + vpc_id = local.vpc_id + tags = { + Name = "${local.env}-private-${local.az_mapping[index(local.nat_gateway_ids, each.key) + 1]}" + } + + route { + cidr_block = "0.0.0.0/0" + nat_gateway_id = each.key + } +} + +locals { + private_route_table_arns = [for i in aws_route_table.private : i.arn] + private_route_table_ids = [for i in aws_route_table.private : i.id] + private_route_table_names = [for i in aws_route_table.private : i.tags["Name"]] +} + +output "private_route_table_arns" { + description = "List of ARNs of the routing tables for the private subnets." + value = local.private_route_table_arns +} + +output "private_route_table_ids" { + description = "List of IDs of the routing tables for the private subnets." + value = local.private_route_table_ids +} + +output "private_route_table_names" { + description = "List of names of the routing tables for the private subnets." + value = local.private_route_table_names +} + +resource "aws_route_table_association" "private" { + for_each = zipmap(local.private_subnet_ids, local.private_route_table_ids) + route_table_id = each.value + subnet_id = each.key +} + +locals { + private_route_table_association_ids = [for i in aws_route_table_association.private : i.id] +} + +output "private_route_table_association_ids" { + description = "List of the route table associations IDs for the private subnets." + value = local.private_route_table_association_ids +}