diff --git a/.github/workflows/apply.yml b/.github/workflows/apply.yml new file mode 100644 index 0000000..f09c4f4 --- /dev/null +++ b/.github/workflows/apply.yml @@ -0,0 +1,110 @@ +name: "Terraform-apply" + +on: + pull_request: + types: [ closed ] + +jobs: + # terraform-module: + # name: "Terraform-modules" + # runs-on: ubuntu-latest + # env: + # AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY_ID }} + # AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRETE_ID }} + # AWS_REGION: 'ap-east-1' + + # steps: + # - name: 'Checkout' + # uses: actions/checkout@master + # - name: 'Terraform Init' + # uses: hashicorp/terraform-github-actions@master + # with: + # tf_actions_version: 0.12.13 + # tf_actions_subcommand: 'init' + # tf_actions_working_dir: './modules/vpc' + # tf_actions_comment: true + # - name: 'Terraform plan' + # uses: hashicorp/terraform-github-actions@master + # with: + # tf_actions_version: 0.12.13 + # tf_actions_subcommand: 'plan' + # tf_actions_working_dir: './modules/vpc' + # tf_actions_comment: true + # - name: 'Terraform apply' + # uses: hashicorp/terraform-github-actions@master + # with: + # tf_actions_version: 0.12.13 + # tf_actions_subcommand: 'apply' + # tf_actions_working_dir: './modules/vpc' + # tf_actions_comment: true + terraform: + name: "Terraform" + needs: terraform-sandbox + runs-on: ubuntu-latest + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRETE_ID }} + AWS_REGION: 'eu-central-1' + + steps: + - name: 'Checkout' + uses: actions/checkout@master + - name: set-env + run: echo "tf_actions_working_dir=$(echo $tf_actions_working_dir | cut -c 1-6)" >> $GITHUB_ENV + - name: 'Terraform Init' + uses: hashicorp/terraform-github-actions@master + with: + tf_actions_version: 0.12.13 + tf_actions_subcommand: 'init' + tf_actions_working_dir: './environments/production' + tf_actions_comment: true + + - name: 'Terraform plan' + uses: hashicorp/terraform-github-actions@master + - name: set env + run: ./bin/deploy.sh -e $tf_actions_working_dir -o plan >> $GITHUB_ENV + with: + tf_actions_version: 0.12.13 + tf_actions_subcommand: 'plan' + tf_actions_working_dir: './environments/production' + tf_actions_comment: true + - name: 'Terraform apply' + uses: hashicorp/terraform-github-actions@master + with: + tf_actions_version: 0.12.13 + tf_actions_subcommand: 'apply' + tf_actions_working_dir: './environments/production' + tf_actions_comment: true + terraform-sandbox: + name: "sandbox-Terraform" + + runs-on: ubuntu-latest + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRETE_ID }} + AWS_REGION: 'ap-south-1' + + steps: + - name: 'Checkout' + uses: actions/checkout@master + - name: 'Terraform Init' + uses: hashicorp/terraform-github-actions@master + with: + tf_actions_version: 0.12.13 + tf_actions_subcommand: 'init' + tf_actions_working_dir: './environments/sandbox' + tf_actions_comment: true + - name: 'Terraform plan' + uses: hashicorp/terraform-github-actions@master + with: + tf_actions_version: 0.12.13 + tf_actions_subcommand: 'plan' + tf_actions_working_dir: './environments/sandbox' + tf_actions_comment: true + - name: 'Terraform apply' + uses: hashicorp/terraform-github-actions@master + with: + tf_actions_version: 0.12.13 + tf_actions_subcommand: 'apply' + tf_actions_working_dir: './environments/sandbox' + tf_actions_comment: true \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..bfce7b5 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,84 @@ +name: "Terraform-Plan" + +on: + pull_request: + branches: [ master ] + +jobs: + terraform-module: + name: "Terraform-modules" + runs-on: ubuntu-latest + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRETE_ID }} + AWS_REGION: 'ap-east-1' + + steps: + - name: 'Checkout' + uses: actions/checkout@master + - name: 'Terraform Init' + uses: hashicorp/terraform-github-actions@master + with: + tf_actions_version: 0.12.13 + tf_actions_subcommand: 'init' + tf_actions_working_dir: './modules/vpc' + tf_actions_comment: true + # - name: 'Terraform plan' + # uses: hashicorp/terraform-github-actions@master + # with: + # tf_actions_version: 0.12.13 + # tf_actions_subcommand: 'plan' + # tf_actions_working_dir: './modules/vpc' + # tf_actions_comment: true + terraform-sandbox: + name: "sandbox-Terraform" + needs: terraform-module + runs-on: ubuntu-latest + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRETE_ID }} + AWS_REGION: 'ap-south-1' + + steps: + - name: 'Checkout' + uses: actions/checkout@master + - name: 'Terraform Init' + uses: hashicorp/terraform-github-actions@master + with: + tf_actions_version: 0.12.13 + tf_actions_subcommand: 'init' + tf_actions_working_dir: './environments/sandbox' + tf_actions_comment: true + - name: 'Terraform plan' + uses: hashicorp/terraform-github-actions@master + with: + tf_actions_version: 0.12.13 + tf_actions_subcommand: 'plan' + tf_actions_working_dir: './environments/sandbox' + tf_actions_comment: true + terraform-prod: + name: "Terraform-prod" + needs: terraform-sandbox + runs-on: ubuntu-latest + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRETE_ID }} + AWS_REGION: 'eu-central-1' + + steps: + - name: 'Checkout' + uses: actions/checkout@master + - name: 'Terraform Init' + uses: hashicorp/terraform-github-actions@master + with: + tf_actions_version: 0.12.13 + tf_actions_subcommand: 'init' + tf_actions_working_dir: './environments/production' + tf_actions_comment: true + - name: 'Terraform plan' + uses: hashicorp/terraform-github-actions@master + with: + tf_actions_version: 0.12.13 + tf_actions_subcommand: 'plan' + tf_actions_working_dir: './environments/production' + tf_actions_comment: true \ No newline at end of file diff --git a/appspec.yml b/appspec.yml deleted file mode 100644 index 5e69e5e..0000000 --- a/appspec.yml +++ /dev/null @@ -1,23 +0,0 @@ -version: 0.0 -os: linux - -files: - - source: ./ - destination: /var/www/html - overwrite: yes - -hooks: - BeforeInstall: - - location: scripts/stop_apache.sh - runas: root - ApplicationStart: - - location: scripts/changepermission.sh - timeout: 3600 - AfterInstall: - - location: scripts/start_apache.sh - timeout: 180 - runas: root - ValidateService: - - location: scripts/status_apache.sh - timeout: 3600 - runas: root diff --git a/bin/deploy.sh b/bin/deploy.sh new file mode 100644 index 0000000..4e2baa5 --- /dev/null +++ b/bin/deploy.sh @@ -0,0 +1,145 @@ +#!/usr/bin/env bash + +# set -x # Un-comment to debug this script + +#TF_LOG=DEBUG; TF_LOG_PATH=~tf.log # Un-comment to debug terraform + +if [ -z "${BASH_VERSINFO[*]}" ] || [ -z "${BASH_VERSINFO[0]}" ] || [ "${BASH_VERSINFO[0]}" -lt 4 ]; then + echo "This script requires Bash version >= 4" + exit 1 +fi + +programname=$0 +SCRIPT_REL_DIR=$(dirname "${0}") +ROOT=$(realpath "$SCRIPT_REL_DIR/../") +cd "$ROOT" || exit + +TERRAFORM_OPTS=() + +# echo 'pull latest code ...' +# git pull origin master + +usage() { + echo "usage: $programname [-e environment] [-o operation]" + echo "MANDATORY:" + echo " -e, --environment VAL specify environment [global sandbox staging production management ops new_sandbox]" + echo " -o, --operation VAL specify operation [plan print_output apply]" + echo "OPTIONAL:" + echo " -a, --auto-approve TERRAFORM_OPTS: auto-approve on apply" + exit 1 +} + +parse_params() { + while [ ! $# -eq 0 ]; do + case "$1" in + --help | -h) + usage + exit + ;; + --environment | -e) + ENV=$2 + if [[ $ENV != "global" && $ENV != "sandbox" && $ENV != "staging" && $ENV != "production" && $ENV != "management" && $ENV != "ops" && $ENV != "new_sandbox" ]]; then + echo "Wrong environment: $ENV. Valid options: global sandbox staging production management ops" + exit 1 + fi + ;; + --operation | -o) + OPER=$2 + if [[ $OPER != "plan" && $OPER != "print_output" && $OPER != "apply" ]]; then + echo "Wrong operation: $OPER. Valid options: plan print_output apply" + exit 1 + fi + ;; + --auto-approve | -a) + if [[ $OPER == "apply" ]]; then + TERRAFORM_OPTS+=('-auto-approve') + fi + ;; + esac + shift + done +} + +print_params() { + echo "-------------------------------" + echo "ENV : $ENV" + echo "OPER : $OPER" + echo "-------------------------------" +} + +select_environment() { + ENVS=("global" "sandbox" "staging" "production" "management" "ops") + echo "Select environment:" + select var in "${ENVS[@]}"; do + ENV=$var + break + done +} + +select_oper() { + OPERS=("apply" "plan" "print_output") + echo "Select operation:" + select oper in "${OPERS[@]}"; do + OPER=$oper + break + done +} + +release_notes() { + RELEASE="RELEASES.md" + if ! grep -q "$PROJECT" $RELEASE; then + echo "#$PROJECT" >>$RELEASE + fi + DATE=$(date +%Y-%m-%d) + sed -i "/$PROJECT/a * **$DATE** - $DESCRIPTION" $RELEASE +} + +get_output_var() { + terraform output -json | jq -r ".$1.value" +} + +# Display output +display_output() { + terraform output +} + +do_project() { + # cd to env folder + cd "environments/$ENV" || exit + + # Deploy architecture + if [[ $OPER == "print_output" ]]; then + display_output + else + echo "Performing $OPER" + terraform "$OPER" "${TERRAFORM_OPTS[@]}" || exit 1 + fi +} + +update_shared_json() { + if [[ $ENV == "global" ]]; then + echo "[Skipping] Uploading shared.json to S3 - global env does not expose shared.json" + elif [[ $OPER != "apply" ]]; then + echo "[Skipping] Uploading shared.json to S3 - terraform outputs are updated only on apply" + else + echo 'Uploading shared.json to S3 ...' + + output=$(terraform output -json) + echo "$output" >shared.json + + aws s3 cp shared.json "s3://lambda-$ENV.spire.io/shared.json" + fi +} + +# execution sequence: +[[ $# -eq 0 ]] && usage +parse_params "$@" +print_params +# select_project +# select_environment +# select_oper +do_project +update_shared_json + +echo '' +echo 'done.' diff --git a/environments/production/variables.tf b/environments/production/variables.tf new file mode 100644 index 0000000..45cdb67 --- /dev/null +++ b/environments/production/variables.tf @@ -0,0 +1,31 @@ +variable "env" { + default = "undefined" +} + +variable "region" { + default = "eu-central-1" +} + +variable "zones" { + default = ["a", "b", "c"] +} + +variable "vpc_cidr" { + default = "10.100.0.0/16" +} + +variable "public_subnet_cidr_blocks" { + default = { + zone0 = "10.100.10.0/24" + zone1 = "10.100.20.0/24" + zone2 = "10.100.30.0/24" + } +} + +variable "private_subnet_cidr_blocks" { + default = { + zone0 = "10.100.11.0/24" + zone1 = "10.100.21.0/24" + zone2 = "10.100.31.0/24" + } +} diff --git a/environments/production/vpc.tf b/environments/production/vpc.tf new file mode 100644 index 0000000..f58b0cd --- /dev/null +++ b/environments/production/vpc.tf @@ -0,0 +1,10 @@ +# VPC +module "vpc" { + source = "../../modules/vpc" + vpc_cidr = var.vpc_cidr + env = var.env + region = var.region + zones = var.zones +} + +## Security groups diff --git a/environments/sandbox/variables.tf b/environments/sandbox/variables.tf new file mode 100644 index 0000000..d9784ea --- /dev/null +++ b/environments/sandbox/variables.tf @@ -0,0 +1,31 @@ +variable "env" { + default = "undefined" +} + +variable "region" { + default = "ap-south-1" +} + +variable "zones" { + default = ["a", "b", "c"] +} + +variable "vpc_cidr" { + default = "10.0.0.0/16" +} + +variable "public_subnet_cidr_blocks" { + default = { + zone0 = "10.0.10.0/24" + zone1 = "10.0.20.0/24" + zone2 = "10.0.30.0/24" + } +} + +variable "private_subnet_cidr_blocks" { + default = { + zone0 = "10.0.11.0/24" + zone1 = "10.0.21.0/24" + zone2 = "10.0.31.0/24" + } +} diff --git a/environments/sandbox/vpc.tf b/environments/sandbox/vpc.tf new file mode 100644 index 0000000..c3108d1 --- /dev/null +++ b/environments/sandbox/vpc.tf @@ -0,0 +1,8 @@ +# VPC +module "vpc" { + source = "../../modules/vpc" + vpc_cidr = var.vpc_cidr + env = var.env + region = var.region + zones = var.zones +} diff --git a/index.php b/index.php deleted file mode 100644 index 18ac52f..0000000 --- a/index.php +++ /dev/null @@ -1,4 +0,0 @@ - diff --git a/modules/core/variables.tf b/modules/core/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/modules/vpc/main.tf b/modules/vpc/main.tf new file mode 100644 index 0000000..ce1d93a --- /dev/null +++ b/modules/vpc/main.tf @@ -0,0 +1,136 @@ +# +# Defines VPC, subnets, security groups, NAT instance, etc. +# + +# VPC +resource "aws_vpc" "default" { + cidr_block = var.vpc_cidr + enable_dns_hostnames = true + + tags = { + Environment = var.env + Name = "spire-vpc-${var.env}" + Provisoning = "terraform" + } +} + +## Public subnets +resource "aws_subnet" "public" { + vpc_id = aws_vpc.default.id + cidr_block = var.public_subnet_cidr_blocks["zone${count.index}"] + availability_zone = "${var.region}${element(var.zones, count.index)}" + count = length(var.zones) + + tags = { + Environment = var.env + Name = "spire-subnet-${var.env}-public-${count.index}" + Type = "spire-subnet-${var.env}-public" + Provisoning = "terraform" + } +} + +### Custom route table for public subnets +resource "aws_route_table" "custom" { + vpc_id = aws_vpc.default.id + + tags = { + Environment = var.env + Name = "spire-${var.env}-public-rt" + Provisoning = "terraform" + } +} + +#### Route for customer route table +resource "aws_route" "custom" { + route_table_id = aws_route_table.custom.id + destination_cidr_block = "0.0.0.0/0" + gateway_id = aws_internet_gateway.default.id + depends_on = [aws_route_table.custom] +} + +### NAT GW eip +resource "aws_eip" "natgw" { + vpc = true + tags = { + Name = "spire-vpc-igw" + Environment = var.env + Provisoning = "terraform" + } +} + +### Internet Gateway +resource "aws_internet_gateway" "default" { + vpc_id = aws_vpc.default.id + tags = { + Name = "spire-nat-sg" + Environment = var.env + Provisoning = "terraform" + } +} + +### NAT Gateway +resource "aws_nat_gateway" "natgw" { + allocation_id = aws_eip.natgw.id + subnet_id = element(aws_subnet.public.*.id, 0) + + tags = { + Environment = var.env + Name = "natgw-${var.env}" + Provisoning = "terraform" + } +} + +#### Associate custom route table with public subnets +resource "aws_route_table_association" "public" { + subnet_id = element(aws_subnet.public.*.id, count.index) + route_table_id = aws_route_table.custom.id + count = length(var.zones) +} + +## Private subnets +resource "aws_subnet" "private" { + vpc_id = aws_vpc.default.id + cidr_block = var.private_subnet_cidr_blocks["zone${count.index}"] + availability_zone = "${var.region}${element(var.zones, count.index)}" + count = length(var.zones) + + tags = { + Environment = var.env + Name = "spire-subnet-${var.env}-private-${count.index}" + Type = "spire-subnet-${var.env}-private" + Provisoning = "terraform" + } +} + +### Main route table +resource "aws_route_table" "main" { + vpc_id = aws_vpc.default.id + + tags = { + Environment = var.env + Name = "spire-${var.env}-private-rt" + Provisoning = "terraform" + } +} + +### Update main route table to use NAT +resource "aws_route" "main" { + route_table_id = aws_route_table.main.id + destination_cidr_block = "0.0.0.0/0" + nat_gateway_id = aws_nat_gateway.natgw.id + depends_on = [aws_nat_gateway.natgw] +} + +### Associate main route table with private subnets +resource "aws_route_table_association" "private" { + subnet_id = element(aws_subnet.private.*.id, count.index) + route_table_id = aws_route_table.main.id + count = length(var.zones) +} + +### Set main route table +resource "aws_main_route_table_association" "main" { + vpc_id = aws_vpc.default.id + route_table_id = aws_route_table.main.id +} + diff --git a/modules/vpc/output.tf b/modules/vpc/output.tf new file mode 100644 index 0000000..846c56e --- /dev/null +++ b/modules/vpc/output.tf @@ -0,0 +1,23 @@ +output "vpc_id" { + value = aws_vpc.default.id +} + +output "vpc_public_subnets" { + value = aws_subnet.public.*.id +} + +output "vpc_private_subnets" { + value = aws_subnet.private.*.id +} + +output "lambda_subnets" { + value = aws_subnet.private.*.id +} + +output "vpc_private_rt" { + value = aws_route_table.main.id +} + +output "vpc_public_rt" { + value = aws_route_table.custom.id +} diff --git a/modules/vpc/variables.tf b/modules/vpc/variables.tf new file mode 100644 index 0000000..83df322 --- /dev/null +++ b/modules/vpc/variables.tf @@ -0,0 +1,31 @@ +variable "env" { + default = "undefined" +} + +variable "region" { + default = "ap-east-1" +} + +variable "zones" { + default = ["a", "b", "c"] +} + +variable "vpc_cidr" { + default = "10.0.0.0/16" +} + +variable "public_subnet_cidr_blocks" { + default = { + zone0 = "10.0.10.0/24" + zone1 = "10.0.20.0/24" + zone2 = "10.0.30.0/24" + } +} + +variable "private_subnet_cidr_blocks" { + default = { + zone0 = "10.0.11.0/24" + zone1 = "10.0.21.0/24" + zone2 = "10.0.31.0/24" + } +} diff --git a/provider.tf b/provider.tf new file mode 100644 index 0000000..4c75b5a --- /dev/null +++ b/provider.tf @@ -0,0 +1,5 @@ +provider "aws" { + region = "us-east-2" + access_key = "AKIAXDSL7DJCYKZR6MFU" + secret_key = "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" +} \ No newline at end of file diff --git a/scripts/changepermission.sh b/scripts/changepermission.sh deleted file mode 100644 index 07c20c9..0000000 --- a/scripts/changepermission.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -# apache config . -chown apache:apache -R /var/www/html diff --git a/scripts/getpull.sh b/scripts/getpull.sh deleted file mode 100644 index 74294b2..0000000 --- a/scripts/getpull.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -# apache config . -cd /var/www/html -chown apache:apache -R ./ diff --git a/scripts/start_apache.sh b/scripts/start_apache.sh deleted file mode 100644 index 9bb3368..0000000 --- a/scripts/start_apache.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -# starting service -service httpd start diff --git a/scripts/status_apache.sh b/scripts/status_apache.sh deleted file mode 100644 index 3b44858..0000000 --- a/scripts/status_apache.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash -#getting status -service httpd status diff --git a/scripts/stop_apache.sh b/scripts/stop_apache.sh deleted file mode 100644 index 65b5455..0000000 --- a/scripts/stop_apache.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -# stoping apache -rm -rf /var/www/html/* -service httpd stop