├── .gitignore ├── LICENSE ├── README.md └── aws ├── DLM-snapshot ├── .gitignore ├── main.tf └── variable.tf ├── Kubernetes ├── README.md ├── cluster │ ├── alb.tf │ ├── eks-cluster.tf │ ├── eks-worker-nodes.tf │ ├── output.tf │ ├── variable.tf │ └── workstation-external-ip.tf ├── kubernetes-server │ ├── ec2.tf │ ├── output.tf │ └── variable.tf ├── main.tf ├── network │ ├── output.tf │ ├── variable.tf │ └── vpc.tf ├── output.tf └── variable.tf ├── agent-install ├── agent-linux.tf ├── agent-windows.tf ├── automation-documents.tf ├── aws-cli.tf ├── mcafee_agen_win2016.tf ├── mcafee_agent_win2012.tf ├── provider.tf ├── snow_soft_agent_installation_automation.json └── variable.tf ├── alb-ssl ├── README.md ├── alb.tf ├── output.tf └── variable.tf ├── ami-sharing ├── main.tf └── variables.tf ├── antivirus-update-ssm-automation ├── antivirus_update_automation_document.json ├── cloudwatch.tf ├── iam.tf ├── lambda.js ├── lambda.tf ├── main.tf ├── ssm.tf └── variables.tf ├── backup_ami ├── main.tf ├── output.tf └── variable.tf ├── config-rules ├── config.tf ├── instance_tags.js ├── lambda.tf ├── main.tf ├── sg-lambda │ ├── security_groups.js │ └── utills.js └── variables.tf ├── domain-join-setup ├── dependencies.tf ├── dhcp.tf ├── hostname.tf ├── linux.tf ├── main.tf ├── ssm.tf ├── variables.tf └── windows.tf ├── ebs-snapshots-setup ├── main.tf └── variables.tf ├── ec2-alarm-cpu-disk-mem ├── dsik-mem-utilization.tf ├── ec2-cpu-system.tf ├── load-balancer.tf ├── provider.tf ├── rds-cpu-disk.tf └── variable.tf ├── ec2-alarms ├── main.tf └── variables.tf ├── ec2-auto-stop-daily ├── lambda.js ├── main.tf └── variables.tf ├── ec2-cost-optimization-using-tags └── main.tf ├── ec2-golden-image-creation ├── domain_unjoin.tf ├── main.tf ├── ssm.tf └── variables.tf ├── ec2-launch-automation ├── amazon_linux_launch_automation_document.json ├── centos_linux_launch_automation_document.json ├── cloudwatch.tf ├── dhcp.tf ├── ec2_launch_automation_document.json ├── iam.tf ├── lambda.js ├── lambda.tf ├── main.tf ├── redhat_linux_launch_automation_document.json ├── ssm.tf ├── ubuntu_linux_launch_automation_document.json ├── variables.tf ├── windows_2012_launch_automation_document.json └── windows_2016_launch_automation_document.json ├── ec2-setup-for-ssm ├── main.tf ├── policy.tf ├── provider.tf └── variables.tf ├── ec2-tags-checker ├── lambda │ ├── lambda.js │ └── utils.js ├── main.tf └── variables.tf ├── iam-cross-account-role ├── main.tf ├── provider.tf └── variables.tf ├── launch-instance-using-vpc-nacl-vpn ├── alb.tf ├── instance.tf ├── main.tf ├── nacl.tf ├── provider.tf ├── rds.tf ├── routetable.tf ├── security_groups.tf ├── variables.tf └── vpn.tf ├── mixed_launch_template ├── .gitignore ├── main.tf ├── output.tf └── variable.tf ├── mysql_dms ├── README.md ├── main.tf └── variables.tf ├── spot-fleet-request ├── README.md ├── main.tf ├── output.tf └── variable.tf ├── ssm-patch-baseline ├── main.tf ├── provider.tf └── variables.tf ├── ssm-tomcat-mongodb-replication ├── mongodb_replication_primary.json ├── mongodb_replication_secondary.json ├── provider.tf ├── ssm.tf ├── tomcat.tf └── variable.tf ├── three-tier ├── README.md ├── main.tf └── variables.tf ├── vpc-endpoints-for-ssm ├── main.tf └── variables.tf ├── vpc-peering-connection ├── main.tf └── variables.tf └── vpc-with-vpn ├── cgw.tf ├── gateway.tf ├── provider.tf ├── rt.tf ├── variables.tf ├── vgw.tf ├── vpc.tf └── vpn.tf /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # .tfvars files 9 | *.tfvars 10 | *.log 11 | *.zip 12 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 tensult 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # terraform 2 | Terraform automation for cloud 3 | ## AWS 4 | 5 | Before starting with Terraform you should have configured your credentials in the AWS folder in your system as shown below. 6 | 7 | ``` 8 | [default] 9 | aws_access_key_id = 10 | aws_secret_access_key = 11 | [prod] 12 | aws_access_key_id = 13 | aws_secret_access_key = 14 | ``` 15 | 16 | The name for the accounts can be anything you want but make sure that in the "main.tf" file that your are using the appropriate name for the profile when configuring. 17 | 18 | ### [Three tier](https://github.com/tensult/terraform/blob/master/aws/three-tier) 19 | Three tier is industry standard for modern web application where we have 3 tiers for following 20 | * Presentation tier (WebAPP tier): Prepares HTMLs by calling App tier 21 | * Application tier (App tier): Prepare data by calling DB or other third party services 22 | * Database tier (DB tier): Stores the data in database. 23 | 24 | Creating three architecture in AWS requires lot of resources like VPC, Subnets, Gateways, Routing tables etc to be created and this has been automated using terraform, for details go [here](https://github.com/tensult/terraform/blob/master/aws/three-tier/README.md). 25 | 26 | ### [RDS MySQL Cross region & Cross account replication using DMS](https://github.com/tensult/terraform/blob/master/aws/mysql_dms) 27 | 28 | Cross region replication helps to quickly recover from AWS region wide failures. Also it will help to serve the customer faster as we can use replica for read traffic and few of them might be closer to replica’s region. 29 | 30 | Cross account replication helps to recover data from replication account when our master AWS account is compromised and we have lost access to the account completely. Such incidents happened in the past where one of the AWS customer account got hacked and the attacker deleted all the data. AWS provides several mechanisms to protect the data but having separate backup account with very limited access and tighter controls will help in unforeseen circumstances. 31 | 32 | You can click on the following links to get a better understanding about DMS. 33 | 1. [Architecture](https://medium.com/tensult/cross-account-and-cross-region-rds-mysql-db-replication-part-1-55d307c7ae65) 34 | 2. [Implementation](https://medium.com/tensult/cross-account-and-cross-region-rds-mysql-db-replication-part-1-55d307c7ae65) 35 | 36 | Please make sure to go through the readme files of each implementation so that the code wll give you the desired output. There is a "main.tf" file which configures the AWS environment while the "variables.tf" file is used to define the variables such as CIDR blocks, names, tags etc for the corresponding AWS resources. This is still a work in progress so feel free to reach out in case something is missing. 37 | 38 | ### [VPC Peering Connections](https://github.com/tensult/terraform/tree/master/aws/vpc-peering-connection) 39 | Creating peering connections between VPCs is a basic networking use-case, and helps reduce load on VPN connections, are reduces latency between the VPCs. here is a "main.tf" file which creates the peering connection requests and the route table entries, and the "variables.tf" file is used to define the variables. You can read the blog post to understand the code [VPC Peering using Terraform](https://medium.com/tensult/vpc-peering-using-terraform-105d554ed04d) 40 | 41 | -------------------------------------------------------------------------------- /aws/DLM-snapshot/.gitignore: -------------------------------------------------------------------------------- 1 | .terraform -------------------------------------------------------------------------------- /aws/DLM-snapshot/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "${var.region}" 3 | profile = "${var.profile}" 4 | } 5 | 6 | resource "aws_iam_role" "dlm_lifecycle_role" { 7 | name = "dlm-lifecycle-role" 8 | 9 | assume_role_policy = < 9 | region = Enter region where you want to apply it
10 | env = Enter Enviourment Name, it show in the ALB tags
11 | vpc_id = Enter Vpc Id to select vpc
12 | subnet_id = Enter Subnets Id eg: subnet-00ca3d68
13 | cer_arn = Enter your certificate arn
14 | 15 | ### Step 2: terraform plan 16 | ` terraform plan -var-file=var.tfvars ` 17 | 18 | ### Step 3: terraform apply 19 | 20 | ` terraform apply -var-file=var.tfvars ` 21 | -------------------------------------------------------------------------------- /aws/alb-ssl/alb.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | profile = "${var.profile}" 3 | region = "${var.region}" 4 | } 5 | 6 | resource "aws_security_group" "alb_sg" { 7 | description = "Allow worker nodes pods to communicate with outsiders" 8 | vpc_id = "${var.vpc_id}" 9 | name = "alb-loadbalancer-sg" 10 | 11 | egress { 12 | from_port = 0 13 | to_port = 0 14 | protocol = "-1" 15 | cidr_blocks = ["0.0.0.0/0"] 16 | } 17 | 18 | tags = { 19 | Name = "alb-sg" 20 | } 21 | } 22 | 23 | resource "aws_security_group_rule" "allow_http" { 24 | type = "ingress" 25 | from_port = 80 26 | to_port = 80 27 | protocol = "tcp" 28 | security_group_id = "${aws_security_group.alb_sg.id}" 29 | source_security_group_id = "0.0.0.0/0" 30 | } 31 | 32 | resource "aws_security_group_rule" "allow_https" { 33 | type = "ingress" 34 | from_port = 443 35 | to_port = 443 36 | protocol = "tcp" 37 | security_group_id = "${aws_security_group.alb_sg.id}" 38 | source_security_group_id = "0.0.0.0/0" 39 | } 40 | 41 | resource "aws_lb" "test" { 42 | name = "${var.alb_name}" 43 | internal = false 44 | load_balancer_type = "application" 45 | security_groups = ["${aws_security_group.alb_sg.id}"] 46 | 47 | # count = "${length(var.subnet_id)}" 48 | subnets = "${var.subnet_id}" 49 | enable_deletion_protection = false 50 | 51 | tags = { 52 | Environment = "${var.env}" 53 | } 54 | } 55 | 56 | resource "aws_lb_target_group" "alb_tg" { 57 | name = "tf-alb-tg" 58 | port = 80 59 | protocol = "HTTP" 60 | vpc_id = "${var.vpc_id}" 61 | } 62 | 63 | resource "aws_lb_listener" "front_end" { 64 | load_balancer_arn = "${aws_lb.test.arn}" 65 | port = 443 66 | protocol = "HTTPS" 67 | 68 | #ssl_policy = "_2a3395ae3cfce2315bb8f40c53867cc8.www.vazid.tk." 69 | certificate_arn = "${var.cer_arn}" 70 | 71 | default_action { 72 | type = "forward" 73 | target_group_arn = "${aws_lb_target_group.alb_tg.arn}" 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /aws/alb-ssl/output.tf: -------------------------------------------------------------------------------- 1 | output "alb_crn" { 2 | description = "Here ALB ARN" 3 | value = "${aws_lb.test.alb_crn}" 4 | } 5 | 6 | -------------------------------------------------------------------------------- /aws/alb-ssl/variable.tf: -------------------------------------------------------------------------------- 1 | variable "alb_name" { 2 | description = "Define ALB Name" 3 | } 4 | 5 | variable "env" { 6 | description = "Define Enviourment name eg - Production" 7 | } 8 | 9 | variable "profile" {} 10 | 11 | variable "region" {} 12 | 13 | variable "vpc_id" {} 14 | 15 | variable "subnet_id" { 16 | type = "list" 17 | } 18 | 19 | variable "cer_arn" { 20 | 21 | } 22 | -------------------------------------------------------------------------------- /aws/ami-sharing/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | profile = "${var.profile}" 3 | region = "${var.region}" 4 | } 5 | 6 | resource "aws_ami_launch_permission" "share" { 7 | count = "${length(var.account_ids)}" 8 | image_id = "${var.ami_id}" 9 | account_id = "${var.account_ids[count.index]}" 10 | } 11 | -------------------------------------------------------------------------------- /aws/ami-sharing/variables.tf: -------------------------------------------------------------------------------- 1 | variable "profile" { 2 | description = "AWS Profile" 3 | default = "default" 4 | } 5 | variable "region" { 6 | description = "AWS region" 7 | default = "ap-south-1" 8 | } 9 | 10 | variable "ami_id" { 11 | description = "EC2 AMI Id" 12 | } 13 | 14 | variable "account_ids" { 15 | description = "List of Account IDs" 16 | type = "list" 17 | } -------------------------------------------------------------------------------- /aws/antivirus-update-ssm-automation/antivirus_update_automation_document.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Antivirus Update Automation", 3 | "schemaVersion": "0.3", 4 | "parameters": { 5 | "instanceIds": { 6 | "type": "StringList", 7 | "description": "InstanceIds to update Antivirus" 8 | }, 9 | "platform": { 10 | "type": "String", 11 | "description": "Operating system platform (windows or linux)" 12 | } 13 | }, 14 | "mainSteps": [{ 15 | "name": "startInstances", 16 | "action": "aws:changeInstanceState", 17 | "maxAttempts": 3, 18 | "timeoutSeconds": 3600, 19 | "onFailure": "Abort", 20 | "inputs": { 21 | "InstanceIds": [ 22 | "{{instanceIds}}" 23 | ], 24 | "DesiredState": "running" 25 | }, 26 | "nextStep": "executeAntivirusUpdate" 27 | }, 28 | { 29 | "name": "executeAntivirusUpdate", 30 | "action": "aws:branch", 31 | "inputs": { 32 | "Choices": [{ 33 | "NextStep": "windowsUpdateAntivirus", 34 | "Variable": "{{platform}}", 35 | "StringEquals": "windows" 36 | }, 37 | { 38 | "NextStep": "linuxUpdateAntivirus", 39 | "Variable": "{{platform}}", 40 | "StringEquals": "linux" 41 | } 42 | ], 43 | "Default": "waitForAntivirusUpdate" 44 | } 45 | }, 46 | { 47 | "name": "windowsUpdateAntivirus", 48 | "action": "aws:runCommand", 49 | "maxAttempts": 3, 50 | "onFailure": "Continue", 51 | "inputs": { 52 | "DocumentName": "AWS-RunPowerShellScript", 53 | "InstanceIds": ["{{instanceIds}}"], 54 | "Parameters": { 55 | "commands": [ 56 | "& \"C:\\Program Files\\McAfee\\Agent\\cmdagent.exe\" -c\n" 57 | ] 58 | } 59 | }, 60 | "nextStep": "waitForAntivirusUpdate" 61 | }, 62 | { 63 | "name": "linuxUpdateAntivirus", 64 | "action": "aws:runCommand", 65 | "maxAttempts": 3, 66 | "onFailure": "Continue", 67 | "inputs": { 68 | "DocumentName": "AWS-RunShellScript", 69 | "InstanceIds": ["{{instanceIds}}"], 70 | "Parameters": { 71 | "commands": [ 72 | "/opt/McAfee/agent/bin/cmdagent -c\n" 73 | ] 74 | } 75 | }, 76 | "nextStep": "waitForAntivirusUpdate" 77 | }, 78 | { 79 | "name": "waitForAntivirusUpdate", 80 | "action": "aws:sleep", 81 | "inputs": { 82 | "Duration": "PT1M" 83 | }, 84 | "nextStep": "stopInstances" 85 | }, 86 | { 87 | "name": "stopInstances", 88 | "action": "aws:changeInstanceState", 89 | "maxAttempts": 3, 90 | "timeoutSeconds": 3600, 91 | "onFailure": "Abort", 92 | "inputs": { 93 | "InstanceIds": [ 94 | "{{instanceIds}}" 95 | ], 96 | "DesiredState": "stopped" 97 | }, 98 | "isEnd": true 99 | } 100 | ] 101 | } -------------------------------------------------------------------------------- /aws/antivirus-update-ssm-automation/cloudwatch.tf: -------------------------------------------------------------------------------- 1 | resource "aws_cloudwatch_event_rule" "weeky_update" { 2 | name = "Weekly-Update-Antivirus" 3 | description = "Update Antivirus on stopped instances" 4 | schedule_expression = "cron(0 16 ? * 1 *)" 5 | } 6 | 7 | resource "aws_cloudwatch_event_target" "antivirus_update_automation" { 8 | rule = "${aws_cloudwatch_event_rule.weeky_update.name}" 9 | target_id = "${aws_lambda_function.lambda_function.function_name}" 10 | arn = "${aws_lambda_function.lambda_function.arn}" 11 | } 12 | -------------------------------------------------------------------------------- /aws/antivirus-update-ssm-automation/iam.tf: -------------------------------------------------------------------------------- 1 | resource "aws_iam_role" "antivirus_automation" { 2 | name = "Antivirus-Update-Automation" 3 | 4 | assume_role_policy = < { 43 | try { 44 | const stoppedInstances = await getStoppedInstances(); 45 | const instanceIds = getInstanceIdsByPlatform(stoppedInstances); 46 | let ssmAutomationExecutionIds = []; 47 | if (instanceIds.windows && instanceIds.windows.length) { 48 | const execution = await ssm.startAutomationExecution({ 49 | DocumentName: process.env.AV_UPDATE_AUTOMATION_DOCUMENT_NAME, 50 | Parameters: { 51 | instanceIds: instanceIds.windows, 52 | platform: "windows" 53 | } 54 | }).promise(); 55 | ssmAutomationExecutionIds.put(execution.AutomationExecutionId); 56 | } 57 | if (instanceIds.linux && instanceIds.linux.length) { 58 | const execution = await ssm.startAutomationExecution({ 59 | DocumentName: process.env.AV_UPDATE_AUTOMATION_DOCUMENT_NAME, 60 | Parameters: { 61 | instanceIds: instanceIds.linux, 62 | platform: "linux" 63 | } 64 | }).promise(); 65 | ssmAutomationExecutionIds.put(execution.AutomationExecutionId); 66 | } 67 | console.log("SSMAutomationExecutionIds", ssmAutomationExecutionIds); 68 | return; 69 | } catch (err) { 70 | throw err; 71 | } 72 | }; -------------------------------------------------------------------------------- /aws/antivirus-update-ssm-automation/lambda.tf: -------------------------------------------------------------------------------- 1 | data "archive_file" "lambda_code" { 2 | type = "zip" 3 | source_file = "lambda.js" 4 | output_path = "lambda.zip" 5 | } 6 | 7 | resource "aws_lambda_function" "lambda_function" { 8 | filename = "${data.archive_file.lambda_code.output_path}" 9 | function_name = "Antivirus-Update-Automation" 10 | role = "${aws_iam_role.antivirus_automation.arn}" 11 | handler = "lambda.handler" 12 | source_code_hash = "${base64sha256(file("${data.archive_file.lambda_code.output_path}"))}" 13 | runtime = "nodejs8.10" 14 | timeout = "300" 15 | environment { 16 | variables = { 17 | AV_UPDATE_AUTOMATION_DOCUMENT_NAME = "${aws_ssm_document.antivirus_update_automation.name}" 18 | } 19 | } 20 | } 21 | 22 | resource "aws_lambda_permission" "allow_cloudwatch" { 23 | statement_id = "AllowExecutionFromCloudWatch" 24 | action = "lambda:InvokeFunction" 25 | function_name = "${aws_lambda_function.lambda_function.function_name}" 26 | principal = "events.amazonaws.com" 27 | source_arn = "${aws_cloudwatch_event_rule.weeky_update.arn}" 28 | } -------------------------------------------------------------------------------- /aws/antivirus-update-ssm-automation/main.tf: -------------------------------------------------------------------------------- 1 | 2 | provider "aws" { 3 | profile = "${var.profile}" 4 | region = "${var.region}" 5 | } 6 | 7 | -------------------------------------------------------------------------------- /aws/antivirus-update-ssm-automation/ssm.tf: -------------------------------------------------------------------------------- 1 | resource "aws_ssm_document" "antivirus_update_automation" { 2 | name = "Antivirus_Update_Automation" 3 | document_type = "Automation" 4 | 5 | content = "${file("antivirus_update_automation_document.json")}" 6 | } -------------------------------------------------------------------------------- /aws/antivirus-update-ssm-automation/variables.tf: -------------------------------------------------------------------------------- 1 | variable "profile" { 2 | description = "AWS Profile" 3 | default = "default" 4 | } 5 | variable "region" { 6 | description = "AWS region" 7 | default = "ap-south-1" 8 | } -------------------------------------------------------------------------------- /aws/backup_ami/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = "${var.region}" 3 | profile = "${var.profile}" 4 | } 5 | 6 | resource "aws_ami_from_instance" "ami-backup" { 7 | name = "${var.ami_name}" #Give unique name of AMI 8 | source_instance_id = "${var.instance_id}" #ID of instance which we are going to take backup 9 | } 10 | -------------------------------------------------------------------------------- /aws/backup_ami/output.tf: -------------------------------------------------------------------------------- 1 | output "ami_id" { 2 | value = "${aws_ami_from_instance.ami-backup.id}" 3 | } 4 | 5 | output "ami_name" { 6 | value = "${aws_ami_from_instance.ami-backup.name}" 7 | } 8 | -------------------------------------------------------------------------------- /aws/backup_ami/variable.tf: -------------------------------------------------------------------------------- 1 | variable "region" {} 2 | 3 | variable "profile" {} 4 | 5 | variable "ami_name" { 6 | description = "Give AMI name" 7 | } 8 | 9 | variable "instance_id" { 10 | description = "Give Instane ID" 11 | } 12 | -------------------------------------------------------------------------------- /aws/config-rules/config.tf: -------------------------------------------------------------------------------- 1 | resource "aws_config_config_rule" "security_groups" { 2 | name = "Security-Groups-Rule" 3 | description = "Checks for open ports" 4 | 5 | source { 6 | owner = "CUSTOM_LAMBDA" 7 | source_identifier = "${aws_lambda_function.security_groups.arn}", 8 | source_detail { 9 | message_type = "ConfigurationItemChangeNotification" 10 | } 11 | } 12 | 13 | scope { 14 | compliance_resource_types = ["AWS::EC2::SecurityGroup"] 15 | } 16 | 17 | depends_on = ["aws_config_configuration_recorder.config_recorder"] 18 | } 19 | 20 | resource "aws_config_config_rule" "instance_tags" { 21 | name = "Instance-Tags-Rule" 22 | description = "Checks if Instance has mandatory tags" 23 | source { 24 | owner = "CUSTOM_LAMBDA" 25 | source_identifier = "${aws_lambda_function.instance_tags.arn}", 26 | source_detail { 27 | message_type = "ConfigurationItemChangeNotification" 28 | } 29 | } 30 | 31 | scope { 32 | compliance_resource_types = ["AWS::EC2::Instance"] 33 | } 34 | 35 | depends_on = ["aws_config_configuration_recorder.config_recorder"] 36 | } 37 | 38 | resource "aws_config_configuration_recorder_status" "recorder_status" { 39 | name = "${aws_config_configuration_recorder.config_recorder.name}" 40 | is_enabled = true 41 | depends_on = ["aws_config_delivery_channel.s3_delivery"] 42 | } 43 | 44 | resource "aws_config_delivery_channel" "s3_delivery" { 45 | s3_bucket_name = "${var.config_bucket_name}" 46 | depends_on = ["aws_config_configuration_recorder.config_recorder"] 47 | } 48 | 49 | resource "aws_config_configuration_recorder" "config_recorder" { 50 | role_arn = "${aws_iam_service_linked_role.config_service_role.arn}" 51 | recording_group { 52 | all_supported = false 53 | include_global_resource_types = false 54 | resource_types = ["AWS::EC2::SecurityGroup", "AWS::EC2::Instance"] 55 | } 56 | } 57 | 58 | resource "aws_iam_service_linked_role" "config_service_role" { 59 | aws_service_name = "config.amazonaws.com" 60 | } -------------------------------------------------------------------------------- /aws/config-rules/lambda.tf: -------------------------------------------------------------------------------- 1 | resource "aws_iam_role" "lambda_role" { 2 | name = "Config-Rule-Lambda" 3 | 4 | assume_role_policy = <{ 4 | return ` 5 | 6 | 7 |

Dear User,

8 | Attention: This is to inform you that the port you have opened does not meet the security compliance standard followed by ${process.env.company_name}. The resource details are attached below. 9 |

Security Group Details:

10 | 11 | 12 | ${prepareMailBody(resourceObject)} 13 |

Note:

14 | 1. Security Group is the firewall of your instance, opening ports unnecessarily can compromise the security.
15 | 2. Please reach out to CIO Team to make changes to the security group(s), if necessary. 16 |

Have a great day!

17 | ` 18 | } 19 | 20 | function prepareHtml(table, headers) { 21 | let htmlBody = `` 22 | headers.forEach((header) => { 23 | htmlBody = header ? htmlBody + `${header}` : htmlBody; 24 | }) 25 | htmlBody = "" + htmlBody + "" 26 | return ` 46 | ${htmlBody}${table}
` 47 | } 48 | 49 | 50 | 51 | function prepareMailBody(instances) { 52 | let htmlTable = ``; 53 | let headers = Object.keys(instances[0]); 54 | instances.forEach((instance) => { 55 | const instanceElements = Object.keys(instance); 56 | instanceElements.forEach((element) => { 57 | htmlTable = instance[element] ? htmlTable + `${instance[element]}` : htmlTable + `Not Mentioned`; 58 | }) 59 | htmlTable = '' + htmlTable + ''; 60 | }); 61 | return prepareHtml(htmlTable, headers); 62 | } 63 | 64 | 65 | exports.securityGroupMailBody = securityGroupMailBody; 66 | -------------------------------------------------------------------------------- /aws/config-rules/variables.tf: -------------------------------------------------------------------------------- 1 | variable "profile" { 2 | description = "AWS Profile" 3 | default = "default" 4 | } 5 | 6 | variable "region" { 7 | description = "AWS region" 8 | default = "ap-south-1" 9 | } 10 | 11 | variable "config_bucket_name" { 12 | description = "AWS Config S3 Bucket name" 13 | } 14 | 15 | variable "account_name" { 16 | description = "AWS Account Name" 17 | } 18 | 19 | variable "ses_email" { 20 | description = "SES verified email" 21 | } 22 | 23 | variable "admin_email" { 24 | description = "Admin email" 25 | } 26 | 27 | variable "notification_emails" { 28 | description = "Email to be notified" 29 | type = "string" 30 | default = "" 31 | } 32 | 33 | variable "company_name" { 34 | description = "Name of the company" 35 | } 36 | -------------------------------------------------------------------------------- /aws/domain-join-setup/dependencies.tf: -------------------------------------------------------------------------------- 1 | resource "aws_ssm_document" "Domainjoin_Dependencies_Linux" { 2 | name = "Domainjoin_Dependencies_Linux" 3 | document_type = "Command" 4 | 5 | content = < /etc/hostname\n", 49 | "echo 127.0.0.1 $hostname.$domain $hostname > /etc/hosts\n", 50 | "echo \"Hostname has changed and rebooting now\"\n", 51 | "reboot" 52 | ] 53 | } 54 | } 55 | ] 56 | } 57 | DOC 58 | } 59 | 60 | resource "aws_ssm_document" "Hostname_Ubuntu" { 61 | name = "Hostname_Change_Ubuntu" 62 | document_type = "Command" 63 | 64 | content = < /etc/hostname\n", 82 | "echo 127.0.0.1 $hostname.$domain > /etc/hosts\n", 83 | "echo \"$ipv4 $hostname\" >> /etc/hosts\n", 84 | "echo \"Hostname has changed and rebooting now\"\n", 85 | "reboot" 86 | ] 87 | } 88 | } 89 | ] 90 | } 91 | DOC 92 | } -------------------------------------------------------------------------------- /aws/domain-join-setup/linux.tf: -------------------------------------------------------------------------------- 1 | resource "aws_ssm_document" "redhatlinux" { 2 | name = "RedHat_CentOS_Domain_Join" 3 | document_type = "Command" 4 | 5 | content = <> /etc/sssd/sssd.conf\n", 27 | "echo dyndns_refresh_interval = 43200 >> /etc/sssd/sssd.conf\n", 28 | "echo dyndns_update_ptr = true >> /etc/sssd/sssd.conf\n", 29 | "echo dyndns_ttl = 3600 >> /etc/sssd/sssd.conf\n", 30 | "echo Updated sssd.conf, now restarting sssd service\n", 31 | "/bin/systemctl restart sssd.service\n", 32 | "cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup\n", 33 | "sed -i -e 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config\n", 34 | "echo Updated sshd_config, now restarting sshd service\n", 35 | "/bin/systemctl restart sshd.service\n", 36 | "echo \"CIOCloudmanagement@$domain ALL=(ALL) ALL\" 37 | >> /etc/sudoers.d/CIOCloudmanagement\n", 38 | "sudo shutdown -r 1" 39 | ] 40 | } 41 | } 42 | ] 43 | } 44 | DOC 45 | } 46 | 47 | resource "aws_ssm_document" "linux" { 48 | name = "Ubuntu_Amzlinux_Domain_Join" 49 | document_type = "Command" 50 | 51 | content = <> /etc/sssd/sssd.conf\n", 73 | "echo dyndns_refresh_interval = 43200 >> /etc/sssd/sssd.conf\n", 74 | "echo dyndns_update_ptr = true >> /etc/sssd/sssd.conf\n", 75 | "echo dyndns_ttl = 3600 >> /etc/sssd/sssd.conf\n", 76 | "echo Updated sssd.conf, now restarting sssd service\n", 77 | "/bin/systemctl restart sssd.service\n", 78 | "cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup\n", 79 | "sed -i -e 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config\n", 80 | "echo Updated sshd_config, now restarting sshd service\n", 81 | "/bin/systemctl restart sshd.service\n", 82 | "echo \"CIOCloudmanagement@$domain ALL=(ALL) ALL\" >> /etc/sudoers.d/CIOCloudmanagement\n", 83 | "sudo shutdown -r 1" 84 | ] 85 | } 86 | } 87 | ] 88 | } 89 | DOC 90 | } 91 | -------------------------------------------------------------------------------- /aws/domain-join-setup/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | profile = "${var.profile}" 3 | region = "${var.region}" 4 | } -------------------------------------------------------------------------------- /aws/domain-join-setup/ssm.tf: -------------------------------------------------------------------------------- 1 | data "aws_kms_key" "ssm" { 2 | key_id = "alias/ssm-key" 3 | } 4 | 5 | resource "aws_ssm_parameter" "domain_username" { 6 | name = "/domain/username" 7 | description = "Domain username" 8 | type = "String" 9 | value = "${var.domain_username}" 10 | overwrite = true 11 | } 12 | 13 | resource "aws_ssm_parameter" "domain_password" { 14 | name = "/domain/password" 15 | description = "Domain password" 16 | type = "SecureString" 17 | value = "${var.domain_password}" 18 | key_id = "${data.aws_kms_key.ssm.arn}" 19 | overwrite = true 20 | } 21 | 22 | resource "aws_ssm_parameter" "ipdns" { 23 | name = "/domain/dns_ip" 24 | description = "DNS IP Address" 25 | type = "String" 26 | value = "${join(",", var.domain_dns_ips)}" 27 | overwrite = true 28 | } 29 | 30 | resource "aws_ssm_parameter" "domain_name" { 31 | name = "/domain/name" 32 | description = "Domain name" 33 | type = "String" 34 | value = "${var.domain_name}" 35 | overwrite = true 36 | } 37 | 38 | resource "aws_ssm_parameter" "domain_ou_path" { 39 | name = "/domain/ou_path" 40 | description = "Domain OU path" 41 | type = "String" 42 | value = "${var.domain_ou_path}" 43 | overwrite = true 44 | } 45 | 46 | -------------------------------------------------------------------------------- /aws/domain-join-setup/variables.tf: -------------------------------------------------------------------------------- 1 | variable "profile" { 2 | description = "AWS Profile" 3 | default = "default" 4 | } 5 | variable "region" { 6 | description = "AWS region" 7 | default = "ap-south-1" 8 | } 9 | 10 | variable "vpc_id" { 11 | description = "VPC ID" 12 | } 13 | 14 | variable "domain_name" { 15 | description = "Domain name" 16 | } 17 | 18 | variable "domain_ou_path" { 19 | description = "Domain OU path" 20 | } 21 | 22 | variable "domain_dns_ips" { 23 | description = "Domain DNS IPs" 24 | type = "list" 25 | } 26 | 27 | variable "amazon_dns" { 28 | description = "Amazon Provided DNS" 29 | default = ["AmazonProvidedDNS"], 30 | type = "list" 31 | } 32 | 33 | 34 | variable "domain_username" { 35 | description = "Domain username" 36 | } 37 | 38 | variable "domain_password" { 39 | description = "Domain password" 40 | } -------------------------------------------------------------------------------- /aws/domain-join-setup/windows.tf: -------------------------------------------------------------------------------- 1 | resource "aws_ssm_document" "windows_2012" { 2 | name = "Windows_2012_Domain_Join" 3 | document_type = "Command" 4 | 5 | content = < { 34 | return reservation.Instances; 35 | }).reduce((allInstances, instancesInReservation) => { 36 | if (instancesInReservation) { 37 | allInstances = allInstances.concat(instancesInReservation); 38 | } 39 | return allInstances; 40 | }, []).filter((instance) => { 41 | return !instance.Tags || !instance.Tags.find((tag) => { 42 | return tag.Key.toLowerCase() === 'donotstop' 43 | }); 44 | }).map((instance) => { 45 | return instance.InstanceId; 46 | }) 47 | } 48 | 49 | function stopRunningEc2Instances(instanceIds, regionName) { 50 | const ec2 = new AWS.EC2({ region: regionName }); 51 | return ec2.stopInstances({ 52 | InstanceIds: instanceIds 53 | }).promise(); 54 | } 55 | 56 | 57 | exports.handler = async (event) => { 58 | // console.log(JSON.stringify(AWS.config)); 59 | try { 60 | let ec2Regions = await getEc2Regions(); 61 | for (let i = 0; i < ec2Regions.Regions.length; i++) { 62 | console.log(ec2Regions.Regions[i].RegionName); 63 | let ec2Instances = await getEc2Instances(ec2Regions.Regions[i].RegionName, 'running'); 64 | if (!ec2Instances.Reservations || ec2Instances.Reservations === 0) { 65 | continue; 66 | } 67 | let filteredRunningEc2InstanceIds = filterStoppableEc2InstanceIds(ec2Instances.Reservations); 68 | console.log(filteredRunningEc2InstanceIds) 69 | if (filteredRunningEc2InstanceIds && filteredRunningEc2InstanceIds.length) { 70 | let doStopRunningEc2Instances = await stopRunningEc2Instances(filteredRunningEc2InstanceIds, ec2Regions.Regions[i].RegionName); 71 | console.log(doStopRunningEc2Instances); 72 | } 73 | } 74 | return; 75 | } catch (err) { 76 | throw err; 77 | } 78 | }; -------------------------------------------------------------------------------- /aws/ec2-auto-stop-daily/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | profile = "${var.profile}" 3 | region = "${var.region}" 4 | } 5 | 6 | resource "aws_iam_role" "lambda_role" { 7 | name = "EC2-Auto-Stop-Lambda" 8 | 9 | assume_role_policy = < { 18 | return !tag.Key.startsWith("aws:"); 19 | }); 20 | 21 | return ec2.createTags({ 22 | Resources: volumeIds, 23 | Tags: volumeTags 24 | }).promise(); 25 | } 26 | 27 | function getInstanceIds(event) { 28 | return event.detail.responseElements.instancesSet.items.map((instance) => { 29 | return instance.instanceId; 30 | }); 31 | } 32 | 33 | function getVolumeIds(ec2DescribeInstancesResponse) { 34 | const volumeIds = []; 35 | for (let reservation of ec2DescribeInstancesResponse.Reservations) { 36 | for (let instance of reservation.Instances) { 37 | for (let blockDevice of instance.BlockDeviceMappings) { 38 | if (blockDevice.Ebs) { 39 | volumeIds.push(blockDevice.Ebs.VolumeId); 40 | } 41 | } 42 | } 43 | } 44 | return volumeIds; 45 | } 46 | 47 | function getInstanceTags(ec2DescribeInstancesResponse) { 48 | return ec2DescribeInstancesResponse.Reservations[0].Instances[0].Tags; 49 | } 50 | 51 | function getInstanceTagsMap(ec2DescribeInstancesResponse) { 52 | return getInstanceTags(ec2DescribeInstancesResponse).reduce((tagsMap, tag) => { 53 | tagsMap[tag.Key] = tag.Value; 54 | return tagsMap; 55 | }, {}); 56 | } 57 | 58 | function executeAutomationDocument(documentName, instanceIds) { 59 | return ssm.startAutomationExecution({ 60 | DocumentName: documentName, 61 | Parameters: { 62 | instanceIds 63 | } 64 | }).promise() 65 | .then((response) => { 66 | console.log("AutomationExecutionId", response.AutomationExecutionId); 67 | }); 68 | } 69 | 70 | function executeAutomation(instanceIds, instanceTags) { 71 | console.log("instanceTags", instanceTags); 72 | if(!instanceTags.os_type) { 73 | console.error("No os_type tag so ignoring automation:", instanceIds); 74 | return; 75 | } 76 | if (instanceTags.os_type.startsWith('AmazonLinux')) { 77 | return executeAutomationDocument(process.env.LAUNCH_AUTOMATION_DOCUMENT_AMAZON_LINUX, instanceIds); 78 | } else if (instanceTags.os_type.startsWith('RedHat')) { 79 | return executeAutomationDocument(process.env.LAUNCH_AUTOMATION_DOCUMENT_REDHAT_LINUX, instanceIds); 80 | } else if (instanceTags.os_type.startsWith('CentOS')) { 81 | return executeAutomationDocument(process.env.LAUNCH_AUTOMATION_DOCUMENT_CENTOS_LINUX, instanceIds); 82 | } else if (instanceTags.os_type.startsWith('Ubuntu')) { 83 | return executeAutomationDocument(process.env.LAUNCH_AUTOMATION_DOCUMENT_UBUNTU_LINUX, instanceIds); 84 | } else if (instanceTags.os_type.startsWith('Windows2012')) { 85 | return executeAutomationDocument(process.env.LAUNCH_AUTOMATION_DOCUMENT_WINDOWS_2012, instanceIds); 86 | } else if (instanceTags.os_type.startsWith('Windows2016')) { 87 | return executeAutomationDocument(process.env.LAUNCH_AUTOMATION_DOCUMENT_WINDOWS_2016, instanceIds); 88 | } 89 | } 90 | 91 | exports.handler = async (event) => { 92 | try { 93 | console.log("Received", JSON.stringify(event, null, 2)); 94 | const instanceIds = getInstanceIds(event); 95 | const ec2DescribeInstancesResponse = await getInstances(instanceIds); 96 | const instanceTags = getInstanceTagsMap(ec2DescribeInstancesResponse); 97 | await executeAutomation(instanceIds, instanceTags); 98 | const volumeIds = getVolumeIds(ec2DescribeInstancesResponse); 99 | await addVolumeTags(volumeIds, getInstanceTags(ec2DescribeInstancesResponse)); 100 | return; 101 | } catch (err) { 102 | throw err; 103 | } 104 | }; -------------------------------------------------------------------------------- /aws/ec2-launch-automation/lambda.tf: -------------------------------------------------------------------------------- 1 | data "archive_file" "lambda_code" { 2 | type = "zip" 3 | source_file = "lambda.js" 4 | output_path = "lambda.zip" 5 | } 6 | 7 | resource "aws_lambda_function" "lambda_function" { 8 | filename = "${data.archive_file.lambda_code.output_path}" 9 | function_name = "Launch-EC2-Instance-Automation" 10 | role = "${aws_iam_role.instance_launch_automation.arn}" 11 | handler = "lambda.handler" 12 | source_code_hash = "${base64sha256(file("${data.archive_file.lambda_code.output_path}"))}" 13 | runtime = "nodejs8.10" 14 | timeout = "300" 15 | 16 | environment { 17 | variables = { 18 | LAUNCH_AUTOMATION_DOCUMENT_AMAZON_LINUX = "${aws_ssm_document.amazon_linux_automation.name}" 19 | LAUNCH_AUTOMATION_DOCUMENT_REDHAT_LINUX = "${aws_ssm_document.redhat_linux_automation.name}" 20 | LAUNCH_AUTOMATION_DOCUMENT_CENTOS_LINUX = "${aws_ssm_document.centos_linux_automation.name}" 21 | LAUNCH_AUTOMATION_DOCUMENT_UBUNTU_LINUX = "${aws_ssm_document.ubuntu_linux_automation.name}" 22 | LAUNCH_AUTOMATION_DOCUMENT_WINDOWS_2012 = "${aws_ssm_document.windows2012_automation.name}" 23 | LAUNCH_AUTOMATION_DOCUMENT_WINDOWS_2016 = "${aws_ssm_document.windows2016_automation.name}" 24 | } 25 | } 26 | } 27 | 28 | resource "aws_lambda_permission" "allow_cloudwatch" { 29 | statement_id = "AllowExecutionFromCloudWatch" 30 | action = "lambda:InvokeFunction" 31 | function_name = "${aws_lambda_function.lambda_function.function_name}" 32 | principal = "events.amazonaws.com" 33 | source_arn = "${aws_cloudwatch_event_rule.ec2_run_instances.arn}" 34 | } 35 | -------------------------------------------------------------------------------- /aws/ec2-launch-automation/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | profile = "${var.profile}" 3 | region = "${var.region}" 4 | } 5 | 6 | -------------------------------------------------------------------------------- /aws/ec2-launch-automation/ssm.tf: -------------------------------------------------------------------------------- 1 | data "aws_kms_key" "ssm" { 2 | key_id = "alias/ssm-key" 3 | } 4 | 5 | resource "aws_ssm_parameter" "domain_username" { 6 | name = "/domain/username" 7 | description = "Domain username" 8 | type = "String" 9 | value = "${var.domain_username}" 10 | overwrite = true 11 | } 12 | 13 | resource "aws_ssm_parameter" "domain_password" { 14 | name = "/domain/password" 15 | description = "Domain password" 16 | type = "SecureString" 17 | value = "${var.domain_password}" 18 | key_id = "${data.aws_kms_key.ssm.arn}" 19 | overwrite = true 20 | } 21 | 22 | resource "aws_ssm_parameter" "ipdns" { 23 | name = "/domain/dns_ip" 24 | description = "DNS IP Address" 25 | type = "String" 26 | value = "${join(",", var.domain_dns_ips)}" 27 | overwrite = true 28 | } 29 | 30 | resource "aws_ssm_parameter" "domain_name" { 31 | name = "/domain/name" 32 | description = "Domain name" 33 | type = "String" 34 | value = "${var.domain_name}" 35 | overwrite = true 36 | } 37 | 38 | resource "aws_ssm_parameter" "domain_ou_path" { 39 | name = "/domain/ou_path" 40 | description = "Domain OU path" 41 | type = "String" 42 | value = "${var.domain_ou_path}" 43 | overwrite = true 44 | } 45 | 46 | data "template_file" "amazon_linux_automation" { 47 | # Render the template once for each instance 48 | template = "${file("amazon_linux_launch_automation_document.json")}" 49 | 50 | vars { 51 | # count.index tells us the index of the instance we are rendering 52 | sudoers = "${var.sudoers}" 53 | } 54 | } 55 | 56 | resource "aws_ssm_document" "amazon_linux_automation" { 57 | name = "Launch_Automation_for_AmazonLinux" 58 | document_type = "Automation" 59 | 60 | content = "${data.template_file.amazon_linux_automation.rendered}" 61 | } 62 | 63 | data "template_file" "redhat_linux_automation" { 64 | # Render the template once for each instance 65 | template = "${file("redhat_linux_launch_automation_document.json")}" 66 | 67 | vars { 68 | # count.index tells us the index of the instance we are rendering 69 | sudoers = "${var.sudoers}" 70 | } 71 | } 72 | 73 | resource "aws_ssm_document" "redhat_linux_automation" { 74 | name = "Launch_Automation_for_RedHatLinux" 75 | document_type = "Automation" 76 | 77 | content = "${data.template_file.redhat_linux_automation.rendered}" 78 | } 79 | 80 | data "template_file" "centos_linux_automation" { 81 | # Render the template once for each instance 82 | template = "${file("centos_linux_launch_automation_document.json")}" 83 | 84 | vars { 85 | # count.index tells us the index of the instance we are rendering 86 | sudoers = "${var.sudoers}" 87 | } 88 | } 89 | 90 | resource "aws_ssm_document" "centos_linux_automation" { 91 | name = "Launch_Automation_for_CentOSLinux" 92 | document_type = "Automation" 93 | 94 | content = "${data.template_file.centos_linux_automation.rendered}" 95 | } 96 | 97 | data "template_file" "ubuntu_linux_automation" { 98 | # Render the template once for each instance 99 | template = "${file("ubuntu_linux_launch_automation_document.json")}" 100 | 101 | vars { 102 | # count.index tells us the index of the instance we are rendering 103 | sudoers = "${var.sudoers}" 104 | } 105 | } 106 | 107 | resource "aws_ssm_document" "ubuntu_linux_automation" { 108 | name = "Launch_Automation_for_UbuntuLinux" 109 | document_type = "Automation" 110 | 111 | content = "${data.template_file.ubuntu_linux_automation.rendered}" 112 | } 113 | 114 | resource "aws_ssm_document" "windows2012_automation" { 115 | name = "Launch_Automation_for_Windows2012" 116 | document_type = "Automation" 117 | 118 | content = "${file("windows_2012_launch_automation_document.json")}" 119 | } 120 | 121 | resource "aws_ssm_document" "windows2016_automation" { 122 | name = "Launch_Automation_for_Windows2016" 123 | document_type = "Automation" 124 | 125 | content = "${file("windows_2016_launch_automation_document.json")}" 126 | } 127 | 128 | resource "aws_ssm_document" "ec2_launch_automation" { 129 | name = "Launch_Automation_for_Any_OS" 130 | document_type = "Automation" 131 | 132 | content = "${file("ec2_launch_automation_document.json")}" 133 | } 134 | -------------------------------------------------------------------------------- /aws/ec2-launch-automation/variables.tf: -------------------------------------------------------------------------------- 1 | variable "profile" { 2 | description = "AWS Profile" 3 | default = "default" 4 | } 5 | 6 | variable "region" { 7 | description = "AWS region" 8 | default = "ap-south-1" 9 | } 10 | 11 | variable "vpc_id" { 12 | description = "VPC ID" 13 | } 14 | 15 | variable "domain_name" { 16 | description = "Domain name" 17 | } 18 | 19 | variable "domain_ou_path" { 20 | description = "Domain OU path" 21 | } 22 | 23 | variable "domain_dns_ips" { 24 | description = "Domain DNS IPs" 25 | type = "list" 26 | } 27 | 28 | variable "amazon_dns" { 29 | description = "Amazon Provided DNS" 30 | default = ["AmazonProvidedDNS"] 31 | type = "list" 32 | } 33 | 34 | variable "domain_username" { 35 | description = "Domain username" 36 | } 37 | 38 | variable "domain_password" { 39 | description = "Domain password" 40 | } 41 | 42 | variable "sudoers" { 43 | description = "sudoers group for linux instances" 44 | } 45 | -------------------------------------------------------------------------------- /aws/ec2-launch-automation/windows_2012_launch_automation_document.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Launch Automation for Windows 2012 instance", 3 | "schemaVersion": "0.3", 4 | "parameters": { 5 | "instanceIds": { 6 | "type": "StringList", 7 | "description": "InstanceIds to run launch setup" 8 | } 9 | }, 10 | "mainSteps": [{ 11 | "name": "waitForInstancesToStart", 12 | "action": "aws:changeInstanceState", 13 | "timeoutSeconds": 600, 14 | "onFailure": "Abort", 15 | "inputs": { 16 | "InstanceIds": [ 17 | "{{instanceIds}}" 18 | ], 19 | "CheckStateOnly": true, 20 | "DesiredState": "running" 21 | }, 22 | "nextStep": "installAWSCLI" 23 | }, 24 | { 25 | "name": "installAWSCLI", 26 | "action": "aws:runCommand", 27 | "onFailure": "Continue", 28 | "timeoutSeconds": 600, 29 | "inputs": { 30 | "DocumentName": "Install_AWSCLI_windows", 31 | "InstanceIds": ["{{instanceIds}}"] 32 | }, 33 | "nextStep": "waitForInstancesToRebootAfterCLI" 34 | }, 35 | { 36 | "name": "waitForInstancesToRebootAfterCLI", 37 | "action": "aws:changeInstanceState", 38 | "timeoutSeconds": 600, 39 | "onFailure": "Abort", 40 | "inputs": { 41 | "InstanceIds": [ 42 | "{{instanceIds}}" 43 | ], 44 | "CheckStateOnly": true, 45 | "DesiredState": "running" 46 | }, 47 | "nextStep": "changeHostname" 48 | }, 49 | { 50 | "name": "changeHostname", 51 | "action": "aws:runCommand", 52 | "onFailure": "Abort", 53 | "timeoutSeconds": 600, 54 | "maxAttempts": 3, 55 | "inputs": { 56 | "DocumentName": "AWS-RunPowerShellScript", 57 | "InstanceIds": ["{{instanceIds}}"], 58 | "Parameters": { 59 | "commands": [ 60 | "$currentHostname = hostname\n", 61 | "$instanceId = ((Invoke-WebRequest -Uri http://169.254.169.254/latest/meta-data/instance-id -UseBasicParsing).Content)\n", 62 | "$newHostname = (aws ec2 describe-instances --instance-id $instanceId --region ap-south-1 --query 'Reservations[0].Instances[0].Tags[?Key==`hostname`].Value' --output text)\n", 63 | "if (!$newHostname) {echo 'hostname (case sensitive) tag is missing on the instance'; exit -1;}\n", 64 | "Rename-computer –computername \"$currentHostname\" –newname \"$newHostname\"\n", 65 | "Restart-Computer -Force" 66 | ] 67 | } 68 | }, 69 | "nextStep": "waitForInstancesToStartAfterReboot" 70 | }, 71 | { 72 | "name": "waitForInstancesToStartAfterReboot", 73 | "action": "aws:changeInstanceState", 74 | "timeoutSeconds": 600, 75 | "onFailure": "Abort", 76 | "inputs": { 77 | "InstanceIds": [ 78 | "{{instanceIds}}" 79 | ], 80 | "CheckStateOnly": true, 81 | "DesiredState": "running" 82 | }, 83 | "nextStep": "joinDomain" 84 | }, 85 | { 86 | "name": "joinDomain", 87 | "action": "aws:runCommand", 88 | "onFailure": "Abort", 89 | "timeoutSeconds": 900, 90 | "inputs": { 91 | "DocumentName": "AWS-RunPowerShellScript", 92 | "InstanceIds": ["{{instanceIds}}"], 93 | "Parameters": { 94 | "commands": [ 95 | "$ipdns = (Get-SSMParameterValue -Name /domain/dns_ip).Parameters[0].Value\n", 96 | "$domain = (Get-SSMParameterValue -Name /domain/name).Parameters[0].Value\n", 97 | "$ouPath = (Get-SSMParameterValue -Name /domain/ou_path).Parameters[0].Value\n", 98 | "$username = (Get-SSMParameterValue -Name /domain/username).Parameters[0].Value\n", 99 | "$domain_username = \"$domain\\$username\"\n", 100 | "$password = (Get-SSMParameterValue -Name /domain/password -WithDecryption $True).Parameters[0].Value | ConvertTo-SecureString -asPlainText -Force\n", 101 | "$credential = New-Object System.Management.Automation.PSCredential($domain_username,$password)\n", 102 | "Set-DnsClientServerAddress \"Ethernet 2\" -ServerAddresses ($ipdns)\n", 103 | "Add-Computer -DomainName $domain -OUPath \"$ouPath\" -Credential $credential\n", 104 | "Restart-Computer -Force" 105 | ] 106 | } 107 | } 108 | } 109 | ] 110 | } -------------------------------------------------------------------------------- /aws/ec2-launch-automation/windows_2016_launch_automation_document.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Launch Automation for Windows 2016 instance", 3 | "schemaVersion": "0.3", 4 | "parameters": { 5 | "instanceIds": { 6 | "type": "StringList", 7 | "description": "InstanceIds to run launch setup" 8 | } 9 | }, 10 | "mainSteps": [{ 11 | "name": "waitForInstancesToStart", 12 | "action": "aws:changeInstanceState", 13 | "timeoutSeconds": 600, 14 | "onFailure": "Abort", 15 | "inputs": { 16 | "InstanceIds": [ 17 | "{{instanceIds}}" 18 | ], 19 | "CheckStateOnly": true, 20 | "DesiredState": "running" 21 | }, 22 | "nextStep": "installAWSCLI" 23 | }, 24 | { 25 | "name": "installAWSCLI", 26 | "action": "aws:runCommand", 27 | "timeoutSeconds": 600, 28 | "onFailure": "Continue", 29 | "inputs": { 30 | "DocumentName": "Install_AWSCLI_windows", 31 | "InstanceIds": ["{{instanceIds}}"] 32 | }, 33 | "nextStep": "waitForInstancesToRebootAfterCLI" 34 | }, 35 | { 36 | "name": "waitForInstancesToRebootAfterCLI", 37 | "action": "aws:changeInstanceState", 38 | "timeoutSeconds": 600, 39 | "onFailure": "Abort", 40 | "inputs": { 41 | "InstanceIds": [ 42 | "{{instanceIds}}" 43 | ], 44 | "CheckStateOnly": true, 45 | "DesiredState": "running" 46 | }, 47 | "nextStep": "changeHostname" 48 | }, 49 | { 50 | "name": "changeHostname", 51 | "action": "aws:runCommand", 52 | "onFailure": "Abort", 53 | "timeoutSeconds": 600, 54 | "inputs": { 55 | "DocumentName": "AWS-RunPowerShellScript", 56 | "InstanceIds": ["{{instanceIds}}"], 57 | "Parameters": { 58 | "commands": [ 59 | "$currentHostname = hostname\n", 60 | "$instanceId = ((Invoke-WebRequest -Uri http://169.254.169.254/latest/meta-data/instance-id -UseBasicParsing).Content)\n", 61 | "$newHostname = (aws ec2 describe-instances --instance-id $instanceId --region ap-south-1 --query 'Reservations[0].Instances[0].Tags[?Key==`hostname`].Value' --output text)\n", 62 | "if (!$newHostname) {echo 'hostname (case sensitive) tag is missing on the instance'; exit -1;}\n", 63 | "Rename-computer –computername \"$currentHostname\" –newname \"$newHostname\"\n", 64 | "Restart-Computer -Force" 65 | ] 66 | } 67 | }, 68 | "nextStep": "waitForInstancesToStartAfterReboot" 69 | }, 70 | { 71 | "name": "waitForInstancesToStartAfterReboot", 72 | "action": "aws:changeInstanceState", 73 | "timeoutSeconds": 600, 74 | "onFailure": "Abort", 75 | "inputs": { 76 | "InstanceIds": [ 77 | "{{instanceIds}}" 78 | ], 79 | "CheckStateOnly": true, 80 | "DesiredState": "running" 81 | }, 82 | "nextStep": "joinDomain" 83 | }, 84 | { 85 | "name": "joinDomain", 86 | "action": "aws:runCommand", 87 | "onFailure": "Abort", 88 | "timeoutSeconds": 600, 89 | "inputs": { 90 | "DocumentName": "AWS-RunPowerShellScript", 91 | "InstanceIds": ["{{instanceIds}}"], 92 | "Parameters": { 93 | "commands": [ 94 | "$ipdns = (Get-SSMParameterValue -Name /domain/dns_ip).Parameters[0].Value\n", 95 | "$domain = (Get-SSMParameterValue -Name /domain/name).Parameters[0].Value\n", 96 | "$ouPath = (Get-SSMParameterValue -Name /domain/ou_path).Parameters[0].Value\n", 97 | "$username = (Get-SSMParameterValue -Name /domain/username).Parameters[0].Value\n", 98 | "$domain_username = \"$domain\\$username\"\n", 99 | "echo $domain_username\n", 100 | "$password = (Get-SSMParameterValue -Name /domain/password -WithDecryption $True).Parameters[0].Value | ConvertTo-SecureString -asPlainText -Force\n", 101 | "$credential = New-Object System.Management.Automation.PSCredential($domain_username,$password)\n", 102 | "Set-DnsClientServerAddress \"Ethernet\" -ServerAddresses $ipdns\n", 103 | "Add-Computer -DomainName $domain -OUPath \"$ouPath\" -Credential $credential\n", 104 | "Restart-Computer -Force" 105 | ] 106 | } 107 | } 108 | } 109 | ] 110 | } -------------------------------------------------------------------------------- /aws/ec2-setup-for-ssm/main.tf: -------------------------------------------------------------------------------- 1 | resource "aws_iam_instance_profile" "ec2_profile" { 2 | name = "EC2-Managed-Instance-Profile" 3 | role = "${aws_iam_role.role.name}" 4 | } 5 | 6 | resource "aws_iam_role" "role" { 7 | name = "EC2-Managed-Instance-Role" 8 | path = "/" 9 | 10 | assume_role_policy = < /etc/hostname\n", 57 | "instanceId=$(curl http://169.254.169.254/latest/meta-data/instance-id)\n", 58 | "ipmongoprimary=$(aws ec2 describe-instances --instance-id $instanceId --region ${region} --query 'Reservations[0].Instances[0].Tags[?Key==`ipmongoprimary`].Value' --output text)\n", 59 | "ipmongosecondary=$(aws ec2 describe-instances --instance-id $instanceId --region ${region} --query 'Reservations[0].Instances[0].Tags[?Key==`ipmongosecondary`].Value' --output text)\n", 60 | "echo $ipmongoprimary mongodb-primary >> /etc/hosts\n", 61 | "echo $ipmongosecondary mongodb-secondary >> /etc/hosts\n", 62 | "reboot" 63 | ] 64 | } 65 | }, 66 | "nextStep": "waitForInstancesToStartAfterReboot" 67 | }, 68 | { 69 | "name": "waitForInstancesToStartAfterReboot", 70 | "action": "aws:changeInstanceState", 71 | "timeoutSeconds": 600, 72 | "onFailure": "Abort", 73 | "inputs": { 74 | "InstanceIds": [ 75 | "{{instanceIds}}" 76 | ], 77 | "CheckStateOnly": true, 78 | "DesiredState": "running" 79 | }, 80 | "nextStep": "installmongoDB" 81 | }, 82 | { 83 | "name": "installmongoDB", 84 | "action": "aws:runCommand", 85 | "onFailure": "Continue", 86 | "inputs": { 87 | "DocumentName": "AWS-RunShellScript", 88 | "InstanceIds": ["{{instanceIds}}"], 89 | "Parameters": { 90 | "commands": [ 91 | "sudo su -\n", 92 | "systemctl start firewalld\n", 93 | "systemctl enable firewalld\n", 94 | "firewall-cmd --permanent --add-port=22/tcp\n", 95 | "firewall-cmd --permanent --add-port=27017/tcp\n", 96 | "firewall-cmd --reload\n", 97 | "cd ~\n", 98 | "yum install wget vim -y\n", 99 | "wget ${mongo_file}\n", 100 | "cp mongo.repo.txt /etc/yum.repos.d/mongodb-org.repo\n", 101 | "yum repolist\n", 102 | "yum install mongodb-org -y\n", 103 | "systemctl start mongod\n", 104 | "sed -i -e 's/ bindIp: 127.0.0.1/# bindIp: 127.0.0.1/g' /etc/mongod.conf\n", 105 | "echo 'replication:' >> /etc/mongod.conf\n", 106 | "echo ' replSetName: \"${customer}\"' >> /etc/mongod.conf\n", 107 | "systemctl restart mongod\n" 108 | ] 109 | } 110 | } 111 | } 112 | ] 113 | } -------------------------------------------------------------------------------- /aws/ssm-tomcat-mongodb-replication/provider.tf: -------------------------------------------------------------------------------- 1 | # Define Provider 2 | provider "aws" { 3 | profile = "${var.profile}" 4 | region = "${var.region}" 5 | } -------------------------------------------------------------------------------- /aws/ssm-tomcat-mongodb-replication/ssm.tf: -------------------------------------------------------------------------------- 1 | data "template_file" "mongodb_replication_primary" { 2 | template = "${file("mongodb_replication_primary.json")}" 3 | 4 | vars { 5 | customer = "${var.customer}" 6 | region = "${var.region}" 7 | mongo_file = "${var.mongo_file}" 8 | } 9 | } 10 | 11 | resource "aws_ssm_document" "mongodb_replication_primary" { 12 | name = "Launch_Automation_for_mongodb_replication_primary" 13 | document_type = "Automation" 14 | 15 | content = "${data.template_file.mongodb_replication_primary.rendered}" 16 | } 17 | 18 | data "template_file" "mongodb_replication_secondary" { 19 | template = "${file("mongodb_replication_secondary.json")}" 20 | 21 | vars { 22 | customer = "${var.customer}" 23 | region = "${var.region}" 24 | mongo_file = "${var.mongo_file}" 25 | } 26 | } 27 | 28 | resource "aws_ssm_document" "mongodb_replication_secondary" { 29 | name = "Launch_Automation_for_mongodb_replication_secondary" 30 | document_type = "Automation" 31 | 32 | content = "${data.template_file.mongodb_replication_secondary.rendered}" 33 | } -------------------------------------------------------------------------------- /aws/ssm-tomcat-mongodb-replication/tomcat.tf: -------------------------------------------------------------------------------- 1 | resource "aws_ssm_document" "tomcat" { 2 | name = "Install_Tomcat" 3 | document_type = "Command" 4 | 5 | content = <